2016-03-26 3 views
3

更新:
ありがとう、ジャンボリー。
これは最終的にstruct Aです。C++ - 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ので、あなたがそれらを渡すとき(const修飾ではない)コンパイラにA&ですcおよびdのコータには、Args &&...argsconst 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'; 
    } 
};