C++函数调用运算符的模板

9

我尝试使用函数调用运算符重载的模板,就像下面的程序:

#include <stdio.h>

struct Apple
{
   template <typename tn> tn value ();
   template <typename tn> tn operator () ();
};

template <> int Apple::value ()
{
   return 10;
}

template <> int Apple::operator () ()
{
   return 10;
}

int main()
{
   Apple apple;
   printf("Value : %d\n", apple<int>());
   printf("Value : %d\n", apple.value<int>());   
   return 0;
}

尽管第二个打印中的值函数调用没有显示任何错误,但第一个打印中的函数调用运算符显示了“预期的主表达式”错误。我不知道我做错了什么。有人能帮我知道问题吗?提前感谢。

1个回答

14

问题出现在调用一个模板化的 operator() (在 main() 的第二行)。在你的情况下,你需要显式指定返回类型,因为它无法被推断出来,正确的方法是:

printf("Value : %d\n", apple.operator()<int>());
operator()()是一个模板成员函数,它以()作为参数。因此,它的名称是operator(),其参数列表是()。要引用它,您需要使用apple.operator()(其名称),然后是<int>(模板参数),然后是()(参数列表)。在心理上用FUNCTION替换名称operator(),这样operator()()就变成了FUNCTION(),您会看到这种模式。在您的情况下,apple<int>()在模板实例化的apple<int>对象上调用非模板operator()(),即apple<int>.operator()(),这不是您想要的。

定义这样一个运算符有用吗?可能不需要,因为它会导致丑陋的语法。


您可以通过在C++14中使用auto返回类型来实现您可能想要的效果,例如:

#include <stdio.h>

struct Apple
{
   template <typename tn> tn value ();
   auto operator () ();
};

template <> int Apple::value ()
{
   return 10;
}

auto Apple::operator () () // not a template anymore, return type is deduced int
{
   return 10;
}

int main()
{
   Apple apple;
   printf("Value : %d\n", apple());
   printf("Value : %d\n", apple.value<int>());   
   return 0;
}

在这个例子中,auto并不会发挥出其优势,因为你可以手动指定int作为返回类型,但在更复杂的声明中,它确实非常有用。


非常好的答案,帮了我很多,谢谢。请问为什么无法推断调用? - Dinesh
@Dinesh,编译器推断类型的唯一方法是将其与某些表达式匹配。在您的情况下,在调用站点没有表达式可以匹配。 - vsoftco
是的,但我在两种情况下都明确指定了类型,我不明白为什么只有在运算符重载函数调用中出现错误。 - Dinesh
使用auto的意义在于何处,既然它与写int完全等效? - T.C.
1
在这种情况下,@T.C.绝对没有任何意义,可能是当返回值为typename T :: some_inner_type :: some_mess时。我只是指出OP不需要一个具有“void”参数的模板函数运算符。 - vsoftco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接