c++ - Invalid template instantation and the metaprogram compiles fine? -


i working on simple solution common "conditional on ill-formed types" problem (like this yesterday question).

in codebase have template hold uninstanced templates , instance them later. this:

template<template<typename...> class f> struct lazy {};  namespace impl {     template<typename l , typename... args>     struct lazy_instance;      template<template<typename...> class f , typename... args>     struct lazy_instance<lazy<f>,args...> : public identity<f<args...>>     {}; }  template<typename l , typename... args> using lazy_instance = typename impl::lazy_instance<l,args...>::type; 

where identity identity metafunction.
used follows:

using vector = lazy<std::vector>; using int_vector = lazy_instance<vector,int>; 

so solution comes mind wrap 2 targets of conditional on way, , instantiate result of conditional, selected template instanced. purpose, have modified lazy , impl::lazy_instance allow pass template parameters @ lazy instantation point:

template<template<typename...> class f , typename... args> struct lazy {};  namespace impl {     template<typename l , typename... args>     struct lazy_instance;      template<template<typename...> class f , typename... args , typename... iargs>     struct lazy_instance<lazy<f,args...>,iargs...> : public identity<f<args...>>     {}; } 

note in case lazy_instance takes template parameters too, ignored. have donde on way have same interface both usage cases.

so our main problem, evaluation of conditional selection of potentially ill-formed types achieved follows:

using ok = lazy_instance<typename std::conditional<true,                                                    lazy<foo,int>,                                                    lazy<foo,bool>                                                   >::type                         >; 

where foo template bool instantation ill-formed, example:

template<typename t> struct foo;  template<> struct foo<int> {}; 

it seems work, isn't? great. couple of minutes later changed boolean flag false, , surprisingly works too! if foo<bool> specialization not defined!

also metaprogram has static_assert bellow check if evaluation of conditional successfull:

static_assert( std::is_same<ok,foo<int>>::value , "mmmmm..." ); 

when changed condition true false, changed test see whats happening there:

static_assert( std::is_same<ok,foo<bool>>::value , "mmmmm..." ); 

and metaprogram passes test too! explicit instantation of foo<bool>, , ok, should alias instance.
have checked there no "no matching specialization foo<bool>" until declare variable of type ok: ok anok;

i'm working clang 3.4, on c++11 mode (-std=c++11). question is: whats happening here? behaviour correct or llvm bug?

edit: here sscce running @ ideone. uses gcc 4.8.1, seems has same behaviour.

long story; short.

you not instantiating foo<bool> in following expression:

std::is_same<ok, foo<bool>>::value; 

when implicit instantiation occur?

14.7.1 implicit instantiation [templ.inst]

5) class template specialization implicitly instantiated if class type used in context requires completely-defined object type or if completeness of class type might affect semantics of program.

7) if implicit instantiation of class template specialization required , template declared not defined, program ill-formed.

what above text says class template implicitly instantiated when used in context requires defined, such when declaring object of said template, or when trying access inside it.

checking if 1 type same not count such context, since merely comparing 2 names.


when completely-defined object required?

the standard makes reference "completely-defined" in several different locations, when explicitly says such object required.

the easiest definition of when need completely-defined object reading following, explains isn't.

3.9p5 types [basic.types]

a class has been declared not defined, or array of unknown size or of incomplete element type, incompletely defined object type. incompletely-defined object types , void types incomplete types (3.9.1). objects shall not defined have incomplete type.

the wording above states long don't declare object of incomplete-type, in clear; ie. our template not implicitly instantiated.

see below example (c) , (d) tries create object of incomplete-type, both (a) , (b) legal since don't cause implicit instantiation.

template<class t> struct a;  typedef a<int> a_int; // (a), legal a<int> *     ptr;     // (b), legal a<int>       foo;     // (c), ill-formed; trying declare object of incomplete-type a<int>::type baz;     // (d), ill-formed; trying reach definition of `a<int>` 

Comments

Popular posts from this blog

database - VFP Grid + SQL server 2008 - grid not showing correctly -

jquery - Set jPicker field to empty value -

.htaccess - htaccess convert request to clean url and add slash at the end of the url -