SFINAE给出了"继承构造函数不继承省略号"的警告

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请注意,有充分的理由不简单地提供一些构造函数重载; 我故意简化方案,使问题尽可能清楚.

编辑:工作简化的测试案例证明的......有必要在这里.(即如果你删除它,它不再编译).

dyp*_*dyp 5

根据...我的理解,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"不能继承"或"不能超载".

实例