GCC 7 中模板类的模板成员函数的专用化
Specialization of a template member function of a template class in GCC 7
我无法使用GCC 7.3编译以下代码:
template <class C>
class BasicScalarFormatter
{
public:
typedef std::basic_string<C> String;
template<typename T>
static String ToString(T val)
{
return String{};
}
};
template<class C>
typename BasicScalarFormatter<C>::String BasicScalarFormatter<C>::ToString<bool>(bool val)
{
return String{};
}
怎么了?
使用 VC2017,如果在类中定义了 ToString,它就会编译:
template <class C>
class BasicScalarFormatter
{
public:
typedef std::basic_string<C> String;
template<typename T>
static String ToString(T val)
{
return ToBasicString<C, T>(val);
}
template<>
static String ToString(bool val)
{
return String{};
}
}
为了使它与GCC一起编译,我将ToString移到了类之外,但它仍然无法编译。GCC 错误消息是:
ource_file.cpp:21:98: error: template-id ‘ToString<bool>’ in declaration of primary template
typename BasicScalarFormatter<C>::String BasicScalarFormatter<C>::ToString<bool>(bool val)
^
source_file.cpp:21:50: error: prototype for ‘BasicScalarFormatter<C>::String BasicScalarFormatter<C>::ToString(bool)’ does not match any in class ‘BasicScalarFormatter<C>’
typename BasicScalarFormatter<C>::String BasicScalarFormatter<C>::ToString<bool>(bool val)
^
source_file.cpp:14:27: error: candidate is: template<class C> template<class T> static BasicScalarFormatter<C>::String BasicScalarFormatter<C>::ToString(T)
static String ToString(T val)
在这里在线查看。
>ToString
是另一个模板类的模板成员。
如果不先
专用外部模板,则无法专用化内部模板。也就是说,您必须首先专门化BasicScalarFormatter
的某个特定实例,然后获取该实例,然后才能专用化其成员模板方法的特定实例。但这种专业化当然只适用于专业BasicScalarFormatter
.
您的明显意图是不专用化外部模板,而是对外部模板类的所有实例的此类成员进行专用化。
这里没有真正干净的解决方案,但这种通用设计模式通常非常简单,智能编译器最终会优化掉额外的重定向:
#include <string>
template<typename C, typename T> class ToStringHelper {
public:
static std::basic_string<C> helper()
{
return std::basic_string<C>();
}
};
template<typename C> class ToStringHelper<C, bool> {
public:
static std::basic_string<C> helper()
{
return std::basic_string<C>();
}
};
template <class C>
class BasicScalarFormatter
{
public:
typedef std::basic_string<C> String;
template<typename T>
static String ToString(T val)
{
return ToStringHelper<C,T>::helper();
}
};
void foo()
{
BasicScalarFormatter<char> c;
c.ToString(0);
c.ToString(true);
}
因此,此时您将在帮助程序类的静态方法中结束。您的最终目标显然是使用原始模板的成员。好吧,你总是可以将this
传递给这个helper()
,并让它对它做一些事情,或者用它来调用调用类的方法。
然后,正如我所说,希望你的编译器能够摆脱这种额外的间接级别,也许在这里和那里散布一些inline
关键字来鼓励它,或者使用蛮力并使用编译器的扩展来强制它内联所有内容。
使用 gcc 8 进行测试。
您缺少一个template
关键字,因为您在类模板中定义了函数模板。这应该有效:
template<class C>
template<>
typename BasicScalarFormatter<C>::String BasicScalarFormatter<C>::ToString<bool>(bool val)
{
return String{};
}
您缺少template <typename C>
,因为您正在使用模板参数C
实现 a 类的方法。
尝试如下:
#include <string>
template <class C>
class BasicScalarFormatter
{
public:
typedef std::basic_string<C> String;
template<typename T>
static String ToString(T val);
};
template <typename C>
template <typename T>
typename BasicScalarFormatter<C>::String BasicScalarFormatter<C>::
ToString(T val)
{
return String{};
}
应该用GCC 7.3
编译,看这里
相关文章:
- 字符串化递归的"std::vector<std::vector<...>>"而不使用部分模板函数专用化
- 使用 C++20 概念模板函数专用化时的依赖项
- 将 c++ 类成员函数专用于模板类
- 使用模板模板参数进行模板定义的函数专用化
- 返回值的简单模板类成员函数专用化
- 已专用类的成员函数专用化
- 部分模板函数专用化enable_if:默认实现
- 使用数组参数进行函数专用化
- 模板函数专用化的内部编译器错误
- 在子类中定义可变参数函数专用化
- 使用模板的构造函数专用化
- 模板函数专用化Enable_if
- 如何将模板构造函数专用化移动到 cpp 文件
- 模板类模板构造函数专用化
- 模板类是否可以用作模板函数专用化的参数
- 未调用数组的函数专用化
- 如何将模板成员函数专用化为另一个模板类
- 模板类的模板函数专用化
- 参数值的自动模板函数专用化
- 如何在类中使用成员函数专用化