在某些情况下,我希望SFINAE去掉类模板的复制构造函数和复制赋值操作符。但是,如果这样做,就会生成一个默认的复制构造函数和一个默认赋值操作符。SFINAE是基于我作为类模板参数传递的标记完成的。问题是,SFINAE只在模板上工作,而复制构造函数/赋值运算符不能是模板。有解决办法吗?
发布于 2015-04-03 10:22:28
此解决方案使用一个有条件不可复制的基类(通过将复制构造函数和复制赋值操作符明确标记为已删除)。
template <bool>
struct NoCopy;
template <>
struct NoCopy<true>
{
// C++11 and later: marking as deleted. Pre-C++11, make the copy stuff private.
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
protected:
~NoCopy() = default; // prevent delete from pointer-to-parent
};
template <>
struct NoCopy<false>
{
// Copies allowed in this case
protected:
~NoCopy() = default; // prevent delete from pointer-to-parent
};示例用法:
template <typename Number>
struct Foo : NoCopy<std::is_integral<Number>::value>
{
Foo() : NoCopy<std::is_integral<Number>::value>{}
{
}
};
int main()
{
Foo<double> a;
auto b = a; // compiles fine
Foo<int> f;
auto g = f; // fails!
}注意:为了避免虚拟继承,NoCopy的析构函数被声明为protected (谢谢提示,@Yakk)。
发布于 2015-04-03 10:21:56
从可复制或不可复制的基础派生的方法是这类问题的标准成语(也请参阅Stefan的评论)。实现它的一种方法是这样的:
template<bool> struct copyable
{
protected:
~copyable() = default;
};
template<> struct copyable<false>
{
copyable(copyable const&) = delete;
copyable&operator=(copyable const&) = delete;
protected:
~copyable() = default;
};
template<bool allow_copy>
class some_class : copyable<allow_copy> { /* ... */ };发布于 2019-08-23 21:04:25
在C++20中,我们可以使用requires子句来约束特殊的成员函数:
template <typename T>
class C {
public:
// ...
C(const C&) requires std::is_copy_constructible_v<T> // for example
{
// ...
}
C(C&&) requires std::is_move_constructible_v<T> // for example
{
// ...
}
// ...
};一个requires子句并不使函数成为函数模板,因此这些函数仍然限定为特殊成员函数,并阻塞生成的默认特殊成员函数。您甚至可以拥有多个,例如,复制构造函数,只要它们有不同的约束。
https://stackoverflow.com/questions/29430090
复制相似问题