For example:
class example{
public:
template <class T> static constexpr T var = T(1.5);
};
int main(){
int a = example::var<int>;
example obj;
int b = obj.var<int>;
return 0;
}
GCC produces error for both:
'example::var<T>' is not a function template
and 'var' is not a member template function
Clang compiles correctly the first one but produces an error for the second: cannot refer to member 'var' in 'example' with '.'
According to the C++14 Standard (ISO/IEC 14882:2014):
Section 14, Paragraph 1.
A variable template at class scope is a static data member template.
Section 9.4, Paragraph 2.
A static member s of class X may be referred to using the qualified-id expression X::s; it is not necessary to use the class member access syntax (5.2.5) to refer to a static member. A static member may be referred to using the class member access syntax, in which case the object expression is evaluated.
Therefore, IMHO, a Variable Template at Class scope (i.e., a Static Data Member Template) could be referred to in both ways. Could it be a bug in the compilers?
The only thing I found to try to justify this behaviour is this sentence in Section 9.4.2, Paragraph 1:
A static data member is not part of the subobjects of a class.
However, the two aforementioned paragraphs are still valid. Besides, I tried the same example referring to other static members such as a variable, a function and a function template, and all of them compile successfully in both GCC and Clang.
class example{
public:
static int constexpr variable = 1;
void static function(){ return; }
template <class T> void static function_template(){ return; }
};
int main(){
example obj;
int a = obj.variable;
int b = example::variable;
obj.function();
example::function();
obj.function_template<int>();
example::function_template<int>();
return 0;
}
Thanks in Advance.
Note 1: compiler versions are clang 3.7.0 and gcc 5.2.1.
Note 2: the keyword static
is required: Variable template at class scope
Note 3: since I want to initialize the variable template, the keyword constexpr
is also required because in my actual code I will instantiate it with float, double and long double (see C++14 Standard (ISO/IEC 14882:2014), Section 9.4.2, Paragraph 3).
Note 4: actual "definitions" of these static data members outside the class (i.e., template <class T> constexpr T example::var;
) are not needed in this example cases. I also tried though, but it makes no difference.