gpt4 book ai didi

c++ - 添加基于模板参数的拷贝构造函数

转载 作者:可可西里 更新时间:2023-11-01 18:24:55 25 4
gpt4 key购买 nike

我有一个类似容器的类,如果基础类型是只移动的,我希望它是只移动的,否则是可复制的。为简单起见,我们假设可复制性由单个 bool 模板参数决定:

template<bool IsCopyable>
struct Foo
{
Foo();
Foo(const Foo&); // only include this when IsCopyable is true
Foo(Foo&&);

Foo& operator=(const Foo&); // only when IsCopyable
Foo& operator=(Foo&&);
};

现在,我不能只删除 SFINAE 复制构造函数,因为这需要将其模板化,而模板化函数不能作为复制构造函数。另外,我不能只在复制构造函数中执行 static_assert()。虽然这会捕获对复制构造函数的错误使用,但它也使类本身可从外部进行复制构造(std::is_copy_constructible 类型特征将产生 true)。

顺便说一下,一个不幸的要求是它需要在 VC++ 2012 中编译,所以我不能使用花哨的表达式 SFINAE、继承 ctors、默认/删除函数或 constexpr if(尽管如此,如果您对 C++17 有一个简洁的解决方案,我仍然想听听它:))

显而易见的方法是使用模板特化。我宁愿不走这条路,因为实际上 Foo 有很多功能,我不想重复自己。尽管如此,这似乎是我唯一的选择,我可以使用基类实现一些代码共享,如下所示:

// Base functionality
template<bool IsCopyable>
struct FooBase
{
FooBase();

// move ctor and assignment can go here
FooBase(FooBase&&);
FooBase& operator=(FooBase&&);

// some generic conversion ctor and assignment that I happen to need
template<class T> FooBase(T&& t);
template<class T> FooBase& operator=(T&&);

// ... all sorts of functionality and datamembers
};

// Foo<false>
template<bool IsCopyable>
struct Foo : FooBase<IsCopyable>
{
// can't use inheriting ctors in VS 2012, wrap the calls manually:
Foo() { }
Foo(Foo&& other) : FooBase<IsCopyable>(std::move(other)) { }
Foo& operator=(Foo&& other)
{
FooBase<IsCopyable>::operator=(std::move(other));
return *this;
}

template<class T> Foo(T&& t) : FooBase<IsCopyable>(std::forward<T>(t)) { }
template<class T> Foo& operator=(T&& t)
{
FooBase<IsCopyable>::operator=(std::forward<T>(t));
return *this;
}
};

// Foo<true>
template<>
struct Foo<true> : FooBase<true>
{
// add these
Foo(const Foo&);
Foo& operator=(const Foo&);

// wrapping calls because of VS 2012:
Foo() { }
Foo(Foo&& other) : FooBase<true>(std::move(other)) { }
Foo& operator=(Foo&& other)
{
FooBase<true>::operator=(std::move(other));
return *this;
}

template<class T> Foo(T&& t) : FooBase<true>(std::forward<T>(t)) { }
template<class T> Foo& operator=(T&& t)
{
FooBase<true>::operator=(std::forward<T>(t));
return *this;
}
};

还是有点啰嗦。幸运的是,一旦您可以使用继承构造函数和默认函数,它就会变得更清晰。不过,我希望有一种更简单的方法,最好是不使用基类。

最佳答案

struct nonesuch {
private:
~nonesuch();
nonesuch(const nonesuch&);
void operator=(const nonesuch&);
};

template<bool IsCopyable>
struct Foo {
Foo(const typename std::conditional<IsCopyable, Foo, nonesuch>::type& other) {
// copy ctor impl here
}
private:
Foo(const typename std::conditional<!IsCopyable, Foo, nonesuch>::type&);
};

同样适用于作业。

关于c++ - 添加基于模板参数的拷贝构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47342384/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com