我有一个功能:
template<class T>
static string
format(T ui, T sentinal, char listSeparator)
{
stringstream s;
if (ui == sentinal)
{
s << "n/a" << listSeparator;
}
else
{
s << ui << listSeparator;
}
return s.str();
}
调用函数的方式是:
output << format(field1,Backend::NA_Value, csvSeparator);
output << format(field2,Backend::NA_Value, csvSeparator);
/// ...etc
以前 field1
和 field2
的类型为 unsigned int
。
决定将这些类型更改为unsigned long long
。
但编译出现错误:
std::string format(T,T,char)' : template parameter 'T' is ambiguous
main.cpp(39) : see declaration of 'format'
could be 'Juint'
'unsigned __int64'
原因是什么?NA_Value?定义为:
static const Juint NA_Value = (Juint) -1;
typedef unsigned int Juint
它无法确定模板T?! 编译器从哪里决定 __int64?
最佳答案
这是一个模板类型推导的问题,其中相同的类型在函数的签名中出现多次。编译器只是不知道您希望 T
是两种类型中的哪一种,因为在调用中这两个出现的类型不同。
您可以像下面这样调用format
(根据您的typedef
替换Juint
):
format(unsigned long long ui, unsigned int sentinal, char listSeparator);
您更改了前一个参数的类型,因此现在它与第二个参数不同。在进行此更改之前,两个参数具有相同的类型。
要解决该问题,您有以下选择:
使模板类型不同。 (see answer by Joachim Pileborg)
在调用函数时,通过显式地将其声明为模板参数来强制使用特定类型。这将自动转换不匹配的参数,就像您习惯于普通函数一样(在这种情况下不会发生类型推导):
output << format<Juint>(field2,Backend::NA_Value, csvSeparator); ^^^^^^^ output << format<unsigned long long>(field2,Backend::NA_Value, csvSeparator); ^^^^^^^^^^^^^^^^^^^^
将其中一个参数转换为另一种类型。这使得两个参数相同并且类型推导将会成功:
output << format(static_cast<Juint>(field2),Backend::NA_Value, csvSeparator); ^^^^^^^^^^^^^^^^^^ output << format(field2,static_cast<unsigned long long>(Backend::NA_Value), csvSeparator); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
同时更改
Juint
的 typedef,使类型再次变为相同,类型推导也成功。添加类型特征/
enable_if
,这会将模板类型限制为满足条件的特定类型类,但就您而言,我认为这不是您想要的。
就个人而言,我希望有另一种选择:最好仅对第一个参数执行类型推导,并强制在调用站点上自动强制转换第二个参数(例如“T”)
但不要推断”参数类型)。但没有这样的选择。
针对您的情况,最好的选择是使 Juint
也具有相同类型(列表中的第四个选项),或者通过选择第一个选项来使您的函数“更通用”。必须注意函数内类型的使用,正如 Joachim Pileborg 在回答中指出的那样,但在您的情况下,在不更改函数体的情况下应该没问题。
关于c++ - 模板参数类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14438398/