Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why instantiation fails for local variable but not for static?

I am trying to find an easy way (with pre C++11, ie no decltype) to document what requirements a template has on a type to work properly. Maybe there are better ways to do this. However, this is my question:

#include <iostream>

template <typename T> struct Foo {
    static const int test = sizeof(T::size);
};

template <typename T> struct DetectAndError {
    DetectAndError() { int test = sizeof(T::size); }
};

struct Bar {};

int main() {
    Foo<Bar> x;                            // NO ERROR ? :/
    // std::cout << x.test << std::endl;   // ERROR :)
    // DetectAndError<Bar> y;              // ERROR :)
}

Why is Foo<Bar> x; not an error? For the other lines I get what I want:

error: 'size' is not a member of 'Bar' 
like image 865
463035818_is_not_a_number Avatar asked Nov 21 '25 08:11

463035818_is_not_a_number


2 Answers

This is because the standard mandates that test will be instantiated only when it is used. Member variables/member functions/static members of a template class aren't instantiated without them being used.

In your case the moment you try to do a x.test compiler tries to find test and subsequently cannot do it as x::size is missing.

The behaviour is pretty much accepted and common and ofcourse as per the standard.

like image 131
themagicalyang Avatar answered Nov 22 '25 23:11

themagicalyang


The other answer is valid, but here's some standardese for it:

N4140 § 14.7.1 [temp.inst]/ 1 and 2

The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or exception-specification s of the class member functions, member classes, scoped member enumerations, static data members and member templates; and it causes the implicit instantiation of the definitions of unscoped member enumerations and member anonymous unions.

the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

Thus, test is only declared in the first line, but yields an error when instantiation is attempted. As for DetectAndError, you're implicitly calling its default constructor. typedef DetectAndError<Foo> foo or DetectAndError<Foo>* ptr should compile with no problems

like image 25
krzaq Avatar answered Nov 22 '25 21:11

krzaq