P i*_*P i 2 c++ inheritance compiler-warnings sfinae c++11
我最近遇到了一个新的警告:
继承构造函数不继承省略号
我正试图管道
Object{42}; // ... into an init that handles integers
Run Code Online (Sandbox Code Playgroud)
...和...
Object{3.14}; // ... into an init that handles FLOATS
Run Code Online (Sandbox Code Playgroud)
...通过使用一些SFINAE狡猾:
#define DECAY(T) typename std::decay<T>::type
#define IS_INTEGRAL(T) std::is_integral< DECAY(T) >::value
#define IS_FLOATING(T) std::is_floating_point< DECAY(T) >::value
#define SUBFAIL_UNLESS(PRED) typename X = \
typename std::enable_if<PRED>::type
// long, float
template<typename T, SUBFAIL_UNLESS(IS_INTEGRAL(T)) >
explicit Object( T&& t ) : Object{ pyob_from_integral(t) } { }
template<typename T, SUBFAIL_UNLESS(IS_FLOATING(T)) >
explicit Object( T&& t, ... ) : Object{ pyob_from_floating(t) } { }
private:
template<typename T> PyObject* pyob_from_integral( T t ) {
cout << "integral"; return nullptr;
}
template<typename T> PyObject* pyob_from_floating(T t) {
cout << "FLOATING"; return nullptr;
}
Run Code Online (Sandbox Code Playgroud)
.在coliru可以看到展示警告的完整代码.
现在...的目的是避免编译器抛出错误,因为它认为我有两个单独的模板模板化构造函数.也就是说,实现它们不相交/相互排斥是不够聪明的.
这个警告有什么意义,以及如何围绕它编码?
PS请注意,有充分的理由不简单地提供一些构造函数重载; 我故意简化方案,使问题尽可能清楚.
编辑:工作简化的测试案例证明的......有必要在这里.(即如果你删除它,它不再编译).
根据...我的理解,OP试图通过引入省略号来解决的问题是,您可能无法定义具有相同签名的两个函数(违反ODR).
这种签名概念扩展到功能模板.但是,函数模板的签名包括其模板参数.根据最新的github草案,基于N4296:
[defns.signature.templ]
签名
<function template> name,parameter type list(8.3.5),enclosing namespace(if any),return type和template parameter list
[basic.link] /9.4和[temp.over.link]指定在什么情况下两个函数模板是等价的.在OP的情况下,您可以通过稍微改变SFINAE的应用方式来使这些功能模板的签名不同:
template<typename T,
typename std::enable_if< std::is_integral<T>::value, int >::type = 0>
explicit Object(T&&);
template<typename T,
typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
explicit Object(T&&);
Run Code Online (Sandbox Code Playgroud)
第二个(非类型)模板参数的类型是依赖于第一个模板参数的表达式.这些表达区分了两个模板; 有关详细信息,请参阅[temp.over.link]/5.在OP中,第二个模板参数只是一种类型.因此,这两个模板的模板参数是等效的,默认模板参数只有一个区别,它不是签名的一部分.
在使用构造函数继承时,省略号的问题在于继承的构造函数会发出省略号.这是构造函数继承的一个怪癖,如[class.inhctor] /1.4中所指定的那样,当继承OP中的两个ctors时,这会导致具有相同签名的候选继承构造函数集中的两个函数模板.我不明白标准如何解决这个问题; clang ++和g ++同意它是非法的,ctor"不能继承"或"不能超载".