- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
假设我正在编写一个类模板 C<T>
持有 T
值,所以 C<T>
仅当 T
时才可复制是可复制的。通常,当模板可能支持或可能不支持某个操作时,您只需定义该操作,并由调用者在不安全时避免调用它:
template <typename T>
class C {
private:
T t;
public:
C(const C& rhs);
C(C&& rhs);
// other stuff
};
但是,这在复制构造函数的情况下会产生问题,因为 is_copy_constructible<C<T>>
即使 T
也是如此不可复制;如果调用该特征,则该特征看不到复制构造函数的格式错误。 这是一个问题,例如,vector
如果 std::is_copy_constructible
有时会避免使用移动构造函数是真的。我该如何解决这个问题?
我相信 is_copy_constructible
如果构造函数被显式或隐式默认,则将做正确的事情:
template <typename T>
class C {
private:
T t;
public:
C(const C& rhs) = default;
C(C&& rhs) = default;
// other stuff
};
但是,并非总是可以构造您的类,以便默认构造函数执行正确的操作。
我能看到的另一种方法是使用 SFINAE 有条件地禁用复制构造函数:
template <typename T>
class C {
private:
T t;
public:
template <typename U = C>
C(typename std::enable_if<std::is_copy_constructible<T>::value,
const U&>::type rhs);
C(C&& rhs);
// other stuff
};
除了丑陋之外,这种方法的问题在于我必须将构造函数设为模板,因为 SFINAE 仅适用于模板。根据定义,复制构造函数不是模板,所以我禁用/启用的东西实际上并不是复制构造函数,因此它不会抑制编译器隐式提供的复制构造函数。
我可以通过显式删除复制构造函数来解决这个问题:
template <typename T>
class C {
private:
T t;
public:
template <typename U = C>
C(typename std::enable_if<std::is_copy_constructible<T>::value,
const U&>::type rhs);
C(const C&) = delete;
C(C&& rhs);
// other stuff
};
但这仍然不能阻止在重载决议期间考虑复制构造函数。这是一个问题,因为在其他条件相同的情况下,普通函数将在重载决议中胜过函数模板,因此当您尝试复制 C<T>
时,普通的复制构造函数被选中,导致构建失败,即使 T
是可复制的。
我发现原则上可行的唯一方法是从主模板中省略复制构造函数,并以部分特化的方式提供它(当 T 不可复制时,使用更多的 SFINAE 技巧来禁用它)。但是,这很脆弱,因为它需要我复制 C
的整个定义。 ,这会造成两个拷贝不同步的重大风险。我可以通过让方法体共享代码来缓解这种情况,但我仍然必须复制类定义和构造函数成员初始化列表,这为错误潜入提供了足够的空间。我可以通过让它们都继承来进一步缓解这种情况来自一个公共(public)基类,但引入继承可能会产生各种不受欢迎的后果。此外,当我想要做的只是禁用一个构造函数时,公共(public)继承似乎是适合这项工作的错误工具。
有没有我没有考虑过的更好的选择?
最佳答案
一个值得注意的方法是对周围的类模板进行部分特化。
template <typename T,
bool = std::is_copy_constructible<T>::value>
struct Foo
{
T t;
Foo() { /* ... */ }
Foo(Foo const& other) : t(other.t) { /* ... */ }
};
template <typename T>
struct Foo<T, false> : Foo<T, true>
{
using Foo<T, true>::Foo;
// Now delete the copy constructor for this specialization:
Foo(Foo const&) = delete;
// These definitions adapt to what is provided in Foo<T, true>:
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
Foo& operator=(Foo const&) = default;
};
这种方式 is_copy_constructible
的特征恰好在 T
is_copy_constructible
的地方得到满足。
关于c++ - 有条件地禁用复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27073082/
谁能解释一下原因: (define a (lambda() (cons a #f))) (car (a)) ==> procedure ((car (a))) ==> (procedure . #f)
这是 PyBrain 网站的摘录。我了解大部分正在发生的事情,但是一行让我完全难住了。我以前从未在 python 代码中看到过这样的东西。这是整个循环,对于上下文: for c in [0,
我是gradle / groovy的新手。我想创建将做一些事情的自定义任务。我的第一个问题是任务完成时该如何做?我可以覆盖doFirst / doLast闭包吗?也许我可以重写某些在开始和结束时都会执
我刚刚开始评估 MS 企业库。他们使用以下指令来获取实例: var customerDb = EnterpriseLibraryContainer.Current.GetInstance("C
这是我的 if else Ansible 逻辑.. - name: Check certs exist stat: path=/etc/letsencrypt/live/{{ rootDomain
我正在使用construct 2.8 对一些失传已久的 Pascal 程序创建的一些文件的 header 进行逆向工程。 header 由许多不同的记录组成,其中一些是可选的,我不确定顺序是否固定。
我在将 getchar() 的输入放入 char *arr[] 数组时遇到问题。我这样做的原因是因为输入数据(将是一个带有命令行参数的文件)将存储在一个 char 指针数组中以传递给 execvp 函
通常我们不能约束类型参数 T派生自密封类型(例如 struct 类型)。这将毫无意义,因为只有一种类型适合,因此不需要泛型。所以约束如下: where T : string 或: where T :
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
#include using namespace std; class A { private: int m_i; friend int main(int argc, char cons
这个问题在这里已经有了答案: Are there legitimate uses for JavaScript's "with" statement? (33 个答案) 关闭 9 年前。 我有这个代
在this answer我看到了下一个 Bash 结构。 yes "$(< file.txt)" 什么意思 "$(< file.txt)" ? 我明白了 命令替换 - $(command)用命令的结
if (a == 1) //do something else if (a == 2) //do something else if (a == 3) //do somethi
关于构造的快速简单的问题。 我有以下用于将项目添加到 ListView 的代码。 ListViewItem item = new ListViewItem(); item.Text = file; i
我想使用 std::vector 来控制给定的内存。首先,我很确定这不是好的做法,但好奇心占了上风,无论如何我都想知道如何做到这一点。 我遇到的问题是这样的方法: vector getRow(unsi
下面显示了一段简单的javascript: var mystring = ("random","ignored","text","h") + ("ello world") 这个字符串会生成 hello
在 Java 中,创建对象的标准方法是使用 MyClass name = new MyClass(); 我也经常看到构造 new MyClass() { /*stuff goes in here*/
我正在编写 C++ ndarray 类。我需要动态大小和编译时大小已知的数组(分别分配自由存储和分配堆栈)。我想支持从嵌套的 std::initializer_list 进行初始化。 动态大小的没问题
我正在将一个项目从 Visual Studio 2005 转换为 Visual Studio 2008,并提出了上述结构。 using Castle.Core.Resource; using Cast
我想知道我在这里的想法是否正确,我主要针对接口(interface)进行编程,所以我想知道下面的类是否应该通过 DI 注入(inject),或者我应该自己实例化一个类... 注意:这些服务保存在我的核
我是一名优秀的程序员,十分优秀!