我使用的类封装了模板专业化的std::变体,例如:
template<typename Type> struct Generic_node {...};
struct Leaf_node : Generic_node<...> {...};
struct Inner_node : Generic_node<...> {...};
struct Node {std::variant<Leaf_node, Inner_node> variant_;};
我试图使用转换移动构造函数从Generic_node
中的函数构造Node
,但编译失败。
我定义了一个模板构造函数,它接受一个右值引用(假设是一个专用类(,并通过将值移动到变量来构造变量,我希望在那里调用转换移动构造函数#(4(。
当我试图创建最小的非工作示例时,我发现问题只从模板函数中显示出来,如果我知道确切的类型(编译器知道的Leaf_node == Generic_node<...>
(,那么move构造就会成功。因此,我认为总会有一些我没有预料到的模板魔法发生。
#include <variant>
template<typename T>
struct Base
{
void f();
};
struct Derived : Base<int> {};
struct Variant
{
// In real program expecting the T to be one of the multiple variants
// Here I use only one variant because it suffices to illustrate the problem
template<typename T>
Variant(T&& t)
:
variant_ {std::move(t)}
{
}
std::variant<Derived> variant_;
};
template<typename T>
void
Base<T>::
f()
{
Variant {std::move(Derived {})}; // can call on exact type
Variant {std::move(Base<T> {})}; // can not call on specialized template type
}
int
main()
{
Derived {}.f();
}
相关编译器错误消息(clang 7,libstdc++-8(:
note: candidate template ignored: substitution failure [with _Tp = Base<int>,
$1 = void, $2 = void]: implicit instantiation of undefined template
'std::variant<Derived>::__to_type_impl<18446744073709551615, false>'
variant(_Tp&& __t)
这个问题很可能与变量无关,而是与变量构造函数的模板实例化中Base<T> == Derived
的相等性有关,编译器似乎没有看到。
模板实例化中发生了什么,为什么编译器不能调用提供的构造函数?
编辑:由于我打算创建一个专门化,我忘记了继承不能意味着类类型相等,即使从技术上讲是在这种特殊情况下。因此,这是一项简单的任务,可以通过从专业基地转移来构建衍生:
struct Derived : Base<int>
{
Derived() = default;
Derived(Base<int>&&) {}
};
如果我是正确的,那么需要为Base的每个派生类显式定义构造函数。
在您给出的示例中,Derived类是一个独立于Base的类。它们有完全相同的成员,相同的方法,但它们仍然是独立的类。
解决这个问题最简单的方法是使用using
语句,而不是将其声明为一个单独的类:
using Derived = Base<int>;