检测(可能是抽象的)基类的受保护构造函数
detecting protected constructors of (possibly abstract) base class
我正在试验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 ...
};
这很有效。。。大多数时候。有时,使用Wrapper
类的代码必须使用SFINAE来检测如何构造这样的Wrapper<T>
。然而,存在以下问题:就重载解析而言,Wrapper<T>
的构造函数将接受任何参数,但如果不能使用这些参数构造类型T
,则编译失败(这不是SFINAE所涵盖的)。
我试图使用enable_if
有条件地启用构造函数模板的不同实例化
template <typename... As, typename std::enable_if<std::is_constructible<T, As && ...>::value, int>::type = 0>
Wrapper(As && ... as) // ...
只要:就可以正常工作
T
的适当构造函数是public
T
不是抽象的
我的问题是:如何摆脱上述两个约束?
我试图通过检查(使用SFINAE和sizeof()
)表达new T(std::declval<As &&>()...)
是否在Wrapper<T>
内形成良好的来克服第一个问题。但这当然不起作用,因为派生类使用其基的受保护构造函数的唯一方法是在成员初始化列表中。
对于第二个,我完全不知道——它是我更需要的,因为有时是Wrapper
实现了T
的抽象函数,使其成为一个完整的类型。
我想要一个解决方案:
- 根据标准是正确的
- 适用于gcc-4.6.*、gcc-4.7.*或clang-3中的任何一个*
谢谢!
这似乎在我的本地GCC上运行良好(4.7,由rubenvb提供)。不过,ideone上的GCC打印了几个"已实现"的编译器内部错误。
我不得不公开Experiment
类的"实现细节",因为出于某些原因(闻起来像个bug),我的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});
}
更新:该代码也适用于Clang。
相关文章:
- 继承和友元函数,从基类访问受保护的成员
- 相同的层次结构,访问基类的受保护成员时的行为不同
- 基类中受保护的纯虚函数如何被基类的友元类使用?
- 派生类无法访问基类的受保护成员
- 无法在赋值运算符中访问基类的受保护方法
- 为什么我无法使用受保护/私有继承访问派生实例中基类的受保护成员?
- 使用基类的C++和修改私有/受保护的属性
- 使从一个基类派生的类能够使用继承的受保护成员
- 无法访问派生类函数内的基类的受保护数据成员
- 派生类如何使用基类的受保护成员
- 如何影响派生类中受保护的基变量
- 访问基类的受保护成员
- 使用指向派生类中的基类的指针访问受基类保护的成员
- 用受保护的继承指向基类方法
- 如何从另一个类的基类访问派生类中的受保护成员
- 在派生的C 类中,访问基类受保护成员作为公共的访问声明
- C++受保护:无法从派生类中访问基的受保护成员
- c++错误:基函数受保护
- 可以从派生类中的静态函数访问基类受保护的成员吗?
- 使用派生类构造函数填充基类受保护成员