As part of a traits class for a larger program, I attempted to create a static class variable which could have a different value depending on the type that the enclosing class template was instantiated with.
I've simplified the relevant code to produce a bare-bones example of what I'm talking about:
#include <iostream>
#include <string>
#include <type_traits>
template <class T, class Enable = void>
struct Foo;
template <class T>
struct Foo<T,
typename std::enable_if<std::is_integral<T>::value>::type
>
{
static std::string message;
};
template <class T>
struct Foo<T,
typename std::enable_if<std::is_floating_point<T>::value>::type
>
{
static std::string message;
};
template <class T, class Enable>
std::string Foo<T, Enable>::message;
With GCC 4.6, this gives a compiler error: template definition of non-template ‘std::string Foo<T, Enable>::message
. The problem occurs because of the last two lines, where I'm just defining the static variable std::string Foo<T, Enable>::message
.
I'm confused why this is happening. The compiler error goes away if I omit the last two lines (but of course that causes linker errors.) Is this a compiler error with GCC?
This only works when your template parameters match the partial specialization:
template <class T>
std::string Foo<T,
typename std::enable_if<std::is_integral<T>::value>::type
>::message;
template <class T>
std::string Foo<T,
typename std::enable_if<std::is_floating_point<T>::value>::type
>::message;
This is specified in section 14.5.4.3 of the C++03 standard. The idea is that a partial specialization is a new template and the template parameters of members that are defined externally have to match the template parameters of the class definition so that it knows which template the member goes with.
In your example, the rule avoids defining the message member for types that are not integral or floating point.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With