ois*_*syn 7 c++ templates sfinae c++11
我有一个类似容器的类,如果底层类型是仅移动的,我只想移动,否则可以复制.为简单起见,我们假设可复制性由单个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&&);
};
Run Code Online (Sandbox Code Playgroud)
现在,我不能只是SFINAE复制ctor,因为这需要使它模板化,模板化的功能不能复制ctor.另外,我不能只static_assert()在拷贝ctor中做一个.虽然这会捕获复制文件的错误用法,但它也使该类固有地从外部复制可构造(std::is_copy_constructible类型特征将产生真实).
顺便说一句,一个不幸的要求是它需要在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;
}
};
Run Code Online (Sandbox Code Playgroud)
它仍然有点冗长.幸运的是,一旦你可以使用继承ctors和默认函数,它就会变得更清晰.尽管如此,我希望有一种更简单的方法,理想情况是不使用基类.
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&);
};
Run Code Online (Sandbox Code Playgroud)
同样适用于作业.
| 归档时间: |
|
| 查看次数: |
461 次 |
| 最近记录: |