【发布时间】:2015-08-29 13:37:30
【问题描述】:
我正在尝试创建一个可根据其模板参数(bool Copyable)复制的类,否则它只能移动。
当通过模板参数bool Copyable启用时,它应该可以通过myclass(myclass&&)和myclass(myclass const&)从类型本身(默认构造函数)构造。
它还可以从 myclass 和其他模板参数构造,我当前的实现通过模板化构造函数和赋值运算符涵盖了这一点。
这里使用零规则通过继承的copyable辅助结构生成默认构造函数和赋值运算符,当bool Copyable为false时禁用复制构造函数和复制赋值运算符。
template<bool>
struct copyable { };
template <>
struct copyable<false>
{
// Disables copy construct & copy assign
copyable() = default;
copyable(copyable const&) = delete;
copyable(copyable&&) = default;
copyable& operator=(copyable const&) = delete;
copyable& operator=(copyable&&) = default;
};
template<typename A, typename B, typename C>
struct storage_t
{
// Implementation depends on A, B and C
};
template<typename A, typename B, typename C, bool Copyable>
class myclass
: public copyable<Copyable>
{
storage_t<A, B, C> _storage;
public:
// It should generate the default constructors and
// assignment operatos dependent on its inherited helper struct copyable.
// Comment this out to disable the error...
// (Implementation omitted)
template<typename A, typename B, typename C>
myclass(myclass<A, B, C, true> const&) { }
template<typename A, typename B, typename C, bool Copyable>
myclass(myclass<A, B, C, Copyable>&&) { }
template<typename A, typename B, typename C>
myclass& operator= (myclass<A, B, C, true> const&) { return *this; }
template<typename A, typename B, typename C, bool Copyable>
myclass& operator= (myclass<A, B, C, Copyable>&&) { return *this; }
// ... comment end
};
通过在 stackoverflow 上解释早期的答案,例如:
- Why does template copy constructor override default copy constructor?
- Copy constructor of template class
- Why can't I override the default copy constructor and assignment operator with template versions in C++
上面写着:
编译器仍会为您生成一个默认的复制构造函数,而不是实例化模板化构造函数。
我认为编译器仍然会生成一个默认的构造函数,尽管提供了一个模板化的构造函数。
但是上面示例代码的编译失败并显示错误消息(msvc 2015):
错误 C2512:“myclass”:没有合适的默认构造函数可用:
myclass<int, int, int, true> mc1;
当我对提供的模板化构造函数和赋值运算符进行注释时,会使用默认构造函数,但无法使用其他模板参数分配 myclass。
一个简单的用法示例是:
/////
// Testing the copyable class
myclass<int, int, int, true> mc1;
// Copy construct
myclass<int, int, int, true> mc2(mc1);
// Copy assign
mc1 = mc2;
/////
// Testing the move only class
myclass<int, int, int, false> mc3;
// Move construct
myclass<int, int, int, false> mc4(std::move(mc3));
// Move assign
mc3 = std::move(mc4);
// Not working part:
// Copy and move from myclass with other template params
myclass<int, int, float, true> mc5;
// Error here:
mc1 = mc5;
有没有办法通过模板参数来禁用复制构造和赋值运算符,并提供模板化的构造函数/赋值运算符?
【问题讨论】:
-
默认如果提供其他构造函数,则不生成构造函数,只需提供
myclass(const myclass&) = default;即可。 -
您的模板化“复制构造函数”并不是真正的复制构造函数 AFAIK。复制构造函数只是那些将与实例化时完全相同的类类型作为第一个参数的构造函数。
-
@Jarod42 当我将复制构造函数声明为默认值时,myclass 可以通过 Copyable = false 访问它。
-
@DenisBlank:我谈到了 default 构造函数(但提供了错误的代码,我的意思是
myclass() = default)。 -
@Jarod42 好的,它可以工作,你能为此创建一个我可以接受的答案吗?