SFINAE远离复制构造函数

use*_*108 14 c++ templates copy-constructor sfinae overload-resolution

在某些条件下,我想要SFINAE远离类模板的复制构造函数和复制赋值运算符.但是如果我这样做,则会生成默认的复制构造函数和默认赋值运算符.SFINAE基于我作为类模板参数传递的标签完成.问题是,SFINAE仅适用于模板,复制构造函数/赋值运算符不能作为模板.是否存在变通方法?

ste*_*fan 12

此解决方案使用条件不可复制的基类(通过明确地将复制构造函数和复制赋值运算符标记为已删除).

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
};
Run Code Online (Sandbox Code Playgroud)

用法示例:

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!
}
Run Code Online (Sandbox Code Playgroud)

注意:NoCopy声明析构函数protected以避免虚拟继承(感谢提示,@ Yakk).


Wal*_*ter 6

从可复制或不可复制的基础派生的方法是这类问题的标准习语(另见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> { /* ... */ };
Run Code Online (Sandbox Code Playgroud)