我正在尝试构建一个模板化的基类,允许分配给它的任何模板类型,如:
#include <type_traits>
#include <utility>
template<typename T1, typename... Types>
class Base
{
public:
//assignment to base or derived class
template<typename T, typename std::enable_if<std::is_base_of<Base<T1, Types...>, T>::value>::type = 0>
Base& operator=(T&& other)
{
if (this != &other)
a = other.a;
return *this;
}
//assignment to other type contained in <T1, Types...>
template<typename T, typename std::enable_if<!std::is_base_of<Base<T1, Types...>, T>::value>::type = 0>
Base& operator=(T&& other)
{
// do some stuff
return *this;
}
private:
int a;
};
正如您所看到的,我正在尝试使用std::enable_if
将分配区分为Base
(移动或复制),并通过包装std::is_base_of
来分配类型。我的印象是T&&
应该绑定到const Base&
,Base&&
,Base&
以及const T&
T&&
等。< / p>
当我尝试通过简单地将参数转发到基类来创建支持赋值的派生类时,就会出现问题:
class Derived : public Base<int, double>
{
public:
// similar pattern here, but call base class' operators
// for both copy/move assignment
// as well as assignment to int or double
template<typename T>
Derived& operator=(T&& other)
{
Base<int, double>::operator=(std::forward<T>(other));
return *this;
}
};
一旦我尝试做我认为应该是有效的赋值,编译器就会告诉我它没有执行模板推导/替换。
int main() {
Derived foo;
int a = 4;
foo = a;
return 0;
}
我在这里做错了什么?请放轻松我。
答案 0 :(得分:5)
两个问题:
对于左值, forwarding-reference (以及模板类型参数T
本身)成为左值参考。在检查它是否是其他类型的子类之前,您应衰减类型T
。
您以错误的方式使用std::enable_if
;如果您想使用::type = 0
语法,则需要使用除默认void
之外的其他类型。
话虽如此,您的std::enable_if
语法应如下所示:
typename std::enable_if<std::is_base_of<Base<T1, Types...>
, typename std::decay<T>::type // decay of T
>::value
, int>::type = 0 // int as a second template argument
完整示例:
template<typename T, typename std::enable_if<std::is_base_of<Base<T1, Types...>, typename std::decay<T>::type>::value, int>::type = 0>
Base& operator=(T&& other)
{
if (this != &other)
a = other.a;
return *this;
}
//assignment to other type contained in <T1, Types...>
template<typename T, typename std::enable_if<!std::is_base_of<Base<T1, Types...>, typename std::decay<T>::type>::value, int>::type = 0>
Base& operator=(T&& other)
{
// do some stuff
return *this;
}