2016-03-26 62 views
3

更新:
谢谢你,Jamboree。
这是最后的struct AC++ - 推导参数包(variadic模板)的构造函数和复制构造函数enable_if_t

struct A 
{ 
    template<class ... Args,class=std::enable_if_t<(sizeof...(Args)!=1)>> 
    A(Args &&...args) 
    { 
     cout<<'v'; 
    } 
    template<class Arg,class=std::enable_if_t<!std::is_base_of<std::remove_reference_t<Arg>,A>::value>> 
    A(Arg &&arg) 
    { 
     cout<<'v'; 
    } 
    A(const A &) 
    { 
     cout<<'c'; 
    } 
    A(A &&) 
    { 
     cout<<'m'; 
    } 
}; 

产地:
关于此代码,

#include<iostream> 
#include<type_traits> 
#include<utility> 
using namespace std; 

struct A 
{ 
    template<class ... Args,class=std::enable_if_t< 
     sizeof...(Args)!=1 
     ||!std::is_same<std::remove_cv_t<std::remove_reference_t<Args>>,A>::value>> 
    A(Args &&...args) 
    { 
     cout<<'v'; 
    } 
    A(const A &) 
    { 
     cout<<'c'; 
    } 
    A(A &&) 
    { 
     cout<<'m'; 
    } 
}; 

int main() 
{ 
    A a{10}; 
    A b{10,20}; 
    A c{b}; 
    const A d{c}; 
    A e{move(c)}; 
} 

的输出是在VC 14.0 vvvvm
但为什么输出不是vvccm
(我想c and d使用拷贝构造函数。我知道,有效的现代C++项目27只使用一个转发参考。)

+1

这应该是形成不良的使用'Args'非膨胀。 –

+0

但是,如果我使用'std :: remove_reference_t ',它会发生编译错误。 – Caesar

回答

2

因为bc,是A&编译器(不是常量限定)当您通过他们到cdArgs &&...args的计数器因此是比const A &更好的匹配。

达到你想要什么,你可以这样来做:

struct A 
{ 
    A() = default; 

    template<class ... Args,std::enable_if_t<(sizeof...(Args)>1), bool> = true> 
    A(Args &&...args) 
    { 
     cout<<'v'; 
    } 

    template<class Arg,std::enable_if_t<!std::is_base_of<A, std::remove_reference_t<Arg>>::value, bool> = true> 
    A(Arg && arg) 
    { 
     cout<<'v'; 
    } 

    A(const A &) 
    { 
     cout<<'c'; 
    } 
    A(A &&) 
    { 
     cout<<'m'; 
    } 
};