【问题标题】:G++ Compiler Error or faulty code? : "template definition of non-template"G++ 编译器错误或错误代码? : "非模板的模板定义"
【发布时间】:2012-04-09 13:28:05
【问题描述】:

作为大型程序的特征类的一部分,我尝试创建一个静态类变量,该变量可能具有不同的值,具体取决于实例化封闭类模板的类型。

我已经简化了相关代码以生成我正在谈论的内容的简单示例:

#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;

对于 GCC 4.6,这会产生编译器错误:template definition of non-template ‘std::string Foo&lt;T, Enable&gt;::message。问题是因为最后两行,我只是定义静态变量std::string Foo&lt;T, Enable&gt;::message。

我很困惑为什么会这样。如果我省略最后两行,编译器错误就会消失(但这当然会导致链接器错误。)这是 GCC 的编译器错误吗?

【问题讨论】:

  • +1 表示“一个简单的例子”。 sscce.org.
  • @Vaughn,这不是这里的问题,但我更新了代码 sn-p。

标签: c++ templates gcc c++11 g++


【解决方案1】:

这仅在您的模板参数与部分特化匹配时有效:

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;

这是在 C++03 标准的第 14.5.4.3 节中指定的。这个想法是,部分特化是一个新模板,并且外部定义的成员的模板参数必须与类定义的模板参数匹配,以便它知道该成员使用哪个模板。

在您的示例中,该规则避免为非整数或浮点类型定义消息成员。

【讨论】:

  • 是否有某种原因单个定义在这里不起作用?这是 C++ 标准规定的,还是 G++ 中的一个怪癖?
  • @GuyGreer:我猜是因为没有为通用模板声明 message 静态字段(仅适用于某些专业化)。无法定义未声明的内容
  • 我在解释中添加了一些细节。
  • @Vaughn,很棒的答案。谢谢。
猜你喜欢
  • 2015-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 2020-06-17
  • 2020-10-13
相关资源
最近更新 更多