subclass 作为模板 base class 的模板模板参数,它又是一个 subclass 函数参数
subclass as template template argument of template base class, which in turn is a subclass function parameter
以下代码
template<template<typename, typename> class T, typename EKeyType, typename EValueType>
class Baseclass
{
};
template<typename EKeyType, typename EValueType>
class Derived : public Baseclass<Derived, EKeyType, EValueType>
{
public:
void foo(const Baseclass<Derived, EKeyType, EValueType>& param){}
};
导致以下编译错误:
MSVC 14: error C3200: 'Derived<EKeyType,EValueType>': invalid template argument for template parameter 'T', expected a class template
clang 3.0.0: error: template argument for template template parameter must be a class template.
然而 Derived
是 一个 class 模板。
当我将代码更改为以下内容时,一切都可以正常编译:
template<template<typename, typename> class T, typename EKeyType, typename EValueType>
class Baseclass
{
};
template<typename EKeyType, typename EValueType> class Derived;
template<typename EKeyType, typename EValueType>
class Derived2 : public Baseclass<Derived, EKeyType, EValueType>
{
public:
void foo(const Baseclass<Derived, EKeyType, EValueType>& param){}
};
表示错误信息具有误导性。
第一个代码有什么问题?
如何让模板 subclass 从模板基 class 继承,其中 subclass 是基 class 的模板模板参数,并且在 subclass 中也有一个成员函数,它引用这个基数 class 作为参数?
第一个片段被 GCC 和 Clang 接受。参见 here。
我似乎记得 MSVC 有一个错误,它认为 Derived
是指注入的 class 名称,而不是模板名称。但是,标准非常清楚,当封闭 class 的名称用作模板模板参数的参数时,它应该被解释为模板([temp.local]/1),所以你的代码是好的.
看来您使用的旧版 Clang 可能存在相同的错误。
作为解决方法,您可以编写 ::Derived
以强制它查找模板名称,而不是注入的 class 名称。
以下代码
template<template<typename, typename> class T, typename EKeyType, typename EValueType>
class Baseclass
{
};
template<typename EKeyType, typename EValueType>
class Derived : public Baseclass<Derived, EKeyType, EValueType>
{
public:
void foo(const Baseclass<Derived, EKeyType, EValueType>& param){}
};
导致以下编译错误:
MSVC 14: error C3200: 'Derived<EKeyType,EValueType>': invalid template argument for template parameter 'T', expected a class template
clang 3.0.0: error: template argument for template template parameter must be a class template.
然而 Derived
是 一个 class 模板。
当我将代码更改为以下内容时,一切都可以正常编译:
template<template<typename, typename> class T, typename EKeyType, typename EValueType>
class Baseclass
{
};
template<typename EKeyType, typename EValueType> class Derived;
template<typename EKeyType, typename EValueType>
class Derived2 : public Baseclass<Derived, EKeyType, EValueType>
{
public:
void foo(const Baseclass<Derived, EKeyType, EValueType>& param){}
};
表示错误信息具有误导性。
第一个代码有什么问题?
如何让模板 subclass 从模板基 class 继承,其中 subclass 是基 class 的模板模板参数,并且在 subclass 中也有一个成员函数,它引用这个基数 class 作为参数?
第一个片段被 GCC 和 Clang 接受。参见 here。
我似乎记得 MSVC 有一个错误,它认为 Derived
是指注入的 class 名称,而不是模板名称。但是,标准非常清楚,当封闭 class 的名称用作模板模板参数的参数时,它应该被解释为模板([temp.local]/1),所以你的代码是好的.
看来您使用的旧版 Clang 可能存在相同的错误。
作为解决方法,您可以编写 ::Derived
以强制它查找模板名称,而不是注入的 class 名称。