Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

G++ Compiler Error or faulty code? : "template definition of non-template"

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?

like image 493
Channel72 Avatar asked Apr 09 '12 13:04

Channel72


1 Answers

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.

like image 80
Vaughn Cato Avatar answered Oct 06 '22 22:10

Vaughn Cato