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.1implicit 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.9p5types[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
Post a Comment