【发布时间】:2021-03-21 21:26:15
【问题描述】:
我有一个模板类,我想要两个复制 ctor。一个用于平凡类型,另一个用于非平凡类型。 以下代码有效(使用一个副本 ctor):
template <typename T>
struct MyStruct
{
MyStruct()
{}
MyStruct(const MyStruct& o)
{
std::cout << "copy ";
foo(o);
}
template <typename U = T, typename std::enable_if_t<!std::is_trivial<U>::value, int> =0>
void foo(const MyStruct& o)
{
std::cout << "Non trivial" << std::endl;
}
template <typename U = T, typename std::enable_if_t<std::is_trivial<U>::value, int> =0>
void foo(const MyStruct& o)
{
std::cout << "Trivial" << std::endl;
}
MyStruct(MyStruct&& o)
{
std::cout << "Move" << std::endl;
}
};
struct MyType
{
MyType(int i){}
};
int main()
{
MyStruct<int> my1;
MyStruct<int> my2(my1);
MyStruct<MyType> mytype1;
MyStruct<MyType> mytype2(mytype1);
}
// prints
// Copy Trivial
// Copy Non trivial
当我尝试对两个复制 ctor 执行相同操作时,似乎它们都没有生成(都被 SFINAE 删除了)
struct MyStruct
{
MyStruct()
{}
template <typename U = T, typename std::enable_if_t<!std::is_trivial<U>::value, int> =0>
MyStruct(const MyStruct& o)
{
std::cout << "Non trivial" << std::endl;
}
template <typename U = T, typename std::enable_if_t<std::is_trivial<U>::value, int> = 0>
MyStruct(const MyStruct& o)
{
std::cout << "Trivial" << std::endl;
}
MyStruct(MyStruct&& o)
{
std::cout << "Move" << std::endl;
}
};
代码无法编译:
main.cpp: In function ‘int main()’:
main.cpp:36:26: error: use of deleted function ‘constexpr MyStruct::MyStruct(const MyStruct&)’
MyStruct<int> my2(my1);
^
main.cpp:5:9: note: ‘constexpr MyStruct::MyStruct(const MyStruct&)’ is implicitly declared as deleted because ‘MyStruct’ declares a move constructor or move assignment operator
struct MyStruct
^~~~~~~~
main.cpp:39:37: error: use of deleted function ‘constexpr MyStruct::MyStruct(const MyStruct&)’
MyStruct<MyType> mytype2(mytype1);
^
main.cpp:5:9: note: ‘constexpr MyStruct::MyStruct(const MyStruct&)’ is implicitly declared as deleted because ‘MyStruct’ declares a move constructor or move assignment operator
struct MyStruct
^~~~~~~~
我尝试用谷歌搜索它,我认为 SFINAE 也应该与复制构造函数一起使用。
请不要建议使用if constexpt 或 requires concept,这个问题是关于SFINAE的。
感谢您的帮助!
【问题讨论】:
-
模板化构造函数永远不是复制构造函数。除了您的两个模板之外,还有一个隐式声明的复制构造函数
MyStruct(const MyStruct& o) = delete;。在这种情况下,它被隐式声明为已删除,因为您的类提供了用户定义的移动构造函数。但它仍然在重载决议中胜过模板化构造函数。 -
谢谢!您和 max66 给出了相似且有用的答案。
标签: c++ constructor sfinae