Grz*_*man 15 c++ templates template-meta-programming perfect-forwarding c++11
我正在试验C++ 11的新功能.在我的设置中,我真的很想使用继承构造函数,但遗憾的是没有编译器实现这些.因此,我试图模拟相同的行为.我可以这样写:
template <class T>
class Wrapper : public T {
public:
template <typename... As>
Wrapper(As && ... as) : T { std::forward<As>(as)... } { }
// ... nice additions to T ...
};
Run Code Online (Sandbox Code Playgroud)
这很有用......大多数时候.有时使用Wrapper类的代码必须使用SFINAE来检测如何Wrapper<T>构造这样的代码.然而,存在以下问题:就重载决策而言,构造函数Wrapper<T>将接受任何参数 - 但是如果不能使用那些构造类型,则编译失败(并且这不包括在SFINAE中)T.
我试图使用有条件地启用构造函数模板的不同实例化 enable_if
template <typename... As, typename std::enable_if<std::is_constructible<T, As && ...>::value, int>::type = 0>
Wrapper(As && ... as) // ...
Run Code Online (Sandbox Code Playgroud)
哪个工作正常,只要:
T是publicT 不是抽象的我的问题是:如何摆脱上述两个限制?
我试图克服所述第一通过检查(使用SFINAE和sizeof())是否表达new T(std::declval<As &&>()...)是公形成内 Wrapper<T>.但是,这当然不起作用,因为派生类可以使用其基类的受保护构造函数的唯一方法是在成员初始化列表中.
对于第二个,我完全不知道 - 它是我需要的更多,因为有时它Wrapper实现了抽象函数T,使其成为一个完整的类型.
我想要一个解决方案:
谢谢!
Joh*_*itb 12
这似乎在我当地的海湾合作委员会中运作良好(4.7,由rubenvb提供).但是,ideone上的GCC会打印几个"已实现"的编译器内部错误.
我不得不将该Experiment类的"实现细节" 公之于众,因为由于某些原因(闻起来像臭虫),我的GCC版本抱怨它们是私有的,即使只有类本身使用它.
#include <utility>
template<typename T, typename Ignored>
struct Ignore { typedef T type; };
struct EatAll {
template<typename ...T>
EatAll(T&&...) {}
};
template<typename T>
struct Experiment : T {
public:
typedef char yes[1];
typedef char no[2];
static void check1(T const&);
static void check1(EatAll);
// if this SFINAE fails, T accepts it
template<typename ...U>
static auto check(int, U&&...u)
-> typename Ignore<no&,
decltype(Experiment::check1({std::forward<U>(u)...}))>::type;
template<typename ...U>
static yes &check(long, U&&...);
public:
void f() {}
template<typename ...U,
typename std::enable_if<
std::is_same<decltype(Experiment::check(0, std::declval<U>()...)),
yes&>::value, int>::type = 0>
Experiment(U &&...u):T{ std::forward<U>(u)... }
{}
};
// TEST
struct AbstractBase {
protected:
AbstractBase(int, float);
virtual void f() = 0;
};
struct Annoyer { Annoyer(int); };
void x(Experiment<AbstractBase>);
void x(Annoyer);
int main() {
x({42});
x({42, 43.f});
}
Run Code Online (Sandbox Code Playgroud)
更新:该代码也适用于Clang.