3

VS2012 をコンパイラとして使用しています。

まずtypedef、不足によるtemplate aliasing

template <typename T>
struct HvVector
{
    typedef std::vector<T> rt;
};

次に、このクラスのオブジェクトをインスタンス化します。

class LetYouDo
{
public:
    template<typename CLASS, typename TYPE>
    LetYouDo(const std::string& name, TYPE (CLASS::*field))
    {
        std::cout << "3" << std::endl;
    }

    template<typename CLASS, typename TYPE>
    LetYouDo(const std::string& name, typename HvVector<TYPE>::rt (CLASS::*field), TYPE* p)
    {
        std::cout << "4" << std::endl;
    }        
};

次のようなクラスの例を使用します。

class Victim
{
public:
    int m1;
    HvVector<int>::rt m2;
};

したがって、実際のケースは次のようになります。

Victim v;
v.m1 = 10;
v.m2.push_back(10);
LetYouDo o1("m1", &Victim::m1);
LetYouDo o2("m2", &Victim::m2, static_cast<int*>(0));

しかし、コンパイラはエラーを出します:

error C2660: 'LetYouDo::LetYouDo' : function does not take 3 arguments

コンパイラが 2 番目のコンストラクタを認識していないように見えますが、なぜですか?

余分なTYPE* pものは、コンパイラに実際の型を与える試みです。typedef型のようなものHvVector<TYPE>::rtは、明確に指定しない限り、テンプレート引数の型を推測できないためです。

編集:

で問題なく動作するオンライン テスト コードを次にgcc 4.8.1示します。これは VS2012 の問題だと思います: ideone.com/YawsaB

4

1 に答える 1

0

問題は、コンストラクターによって行われる型推論にあります。クラスをコンストラクタではなくテンプレートにすることで、型を明示的に作成できます。これは機能します:

template<typename CLASS, typename TYPE>
class LetYouDo
{
public:
    LetYouDo(const std::string& name, TYPE (CLASS::*field))
    {
        std::cout << "3" << std::endl;
    }

    LetYouDo(const std::string& name, typename HvVector<TYPE>::rt (CLASS::*field), TYPE* p)
    {
        std::cout << "4" << std::endl;
    }        
};

LetYouDo<Victim,int> o1("m1", &Victim::m1);
LetYouDo<Victim,int> o2("m2", &Victim::m2, static_cast<int*>(0));

コンストラクターをメソッドに変換すると、コンパイラーから適切なメッセージが表示されます。試す:

class LetYouDo
{

    template<typename CLASS, typename TYPE>
    void LetYouDoInit(const std::string& name, typename HvVector<TYPE>::rt (CLASS::*field), TYPE* p)
    {
        std::cout << "4" << std::endl;
    }        
};

LetYouDo o2;
o2.LetYouDoInit("m2", &Victim::m2, static_cast<int*>(0));

あなたは得るでしょう:

1>c:\users\all\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp(47): error C2784: 'void LetYouDo::LetYouDoInit(const std::string &,HvVector<TYPE>::rt CLASS::* ,TYPE *)' : could not deduce template argument for 'HvVector<TYPE>::rt CLASS::* ' from 'std::vector<T,std::allocator<_Ty>> Victim::* '
1>          with
1>          [
1>              T=int
1>  ,            _Ty=int
1>          ]
1>          c:\users\all\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp(24) : see declaration of 'LetYouDo::LetYouDoInit'
1>c:\users\all\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp(47): error C2780: 'void LetYouDo::LetYouDoInit(const std::string &,TYPE CLASS::* )' : expects 2 arguments - 3 provided
1>          c:\users\all\documents\visual studio 2013\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp(18) : see declaration of 'LetYouDo::LetYouDoInit'

タイプを明示的にすると、メッセージは消えます。

LetYouDo o2;
o2.LetYouDoInit<Victim,int>("m2", &Victim::m2, static_cast<int*>(0));
于 2014-09-25T17:21:50.507 に答える