Почему перегрузка этого конструктора не может работать? (шаблон и typedef встречаются)

Я использую 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

Похоже, компилятор не знает моего второго конструктора, почему?

Экстра TYPE* p это попытка дать компилятору мой реальный тип, потому что typedef типа как HvVector<TYPE>::rt не могу вывести тип аргумента шаблона, если я не укажу его четко.

Редактировать:

Вот онлайн тестовый код, который отлично работает с gcc 4.8.1, так что я думаю, что это проблема VS2012: ideone.com/YawsaB

3

Решение

Проблема в выводе типа, сделанном конструкторами. Вы можете явно сделать типы, сделав класс шаблоном, а не его конструкторами. Это работает:

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));
0

Другие решения


По вопросам рекламы [email protected]