我使用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
答案 0 :(得分: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));