为什么模板参数没有推导只用作返回类型?

mil*_*bos 4 c++ templates language-lawyer template-argument-deduction

如果我不在函数参数列表中使用 tempate 参数(类型)-> 仅作为返回类型,则没有推论:

template <typename T>
T zero() { return 0; }

int main()
{
    int x = zero();
}
Run Code Online (Sandbox Code Playgroud)

给出:

a.cpp:15:18: error: no matching function for call to ‘zero()’
     int x = zero();
                  ^
a.cpp:11:3: note: candidate: ‘template<class T> T zero()’
 T zero() { return 0; }
   ^~~~
a.cpp:11:3: note:   template argument deduction/substitution failed:
a.cpp:15:18: note:   couldn't deduce template parameter ‘T’
     int x = zero();
Run Code Online (Sandbox Code Playgroud)

编译的唯一方法是在尖括号中指定模板类型:

template <typename T>
T zero() { return 0; }

int main()
{
    int x = zero<int>();
}
Run Code Online (Sandbox Code Playgroud)
  1. 所以我的问题是,为什么 g++可以从模板函数的参数列表中推断出类型,但不能返回类型中推断出它(编译时编译器main也知道它,所以它知道类型)。

  2. 当模板函数在其参数列表中使用模板类型时,为模板函数提供尖括号中的类型是任意的(因为推论)?因此,作为一个好的做法,无论函数是如何声明的,我是否应该始终在花括号中提供类型?

第二个问题不太好读。用简单的话来说 -> 我应该foo<T>(arg, ...)每次都使用(提供类型),无论函数声明如何?即使它可以由编译器推断出来,但我还是会提供类型以进行良好实践?

Ada*_*amF 6

通常不可能根据其返回类型推导出函数。但是,如果您使用自动类型转换 C++ 功能,那么您可以实现您所需要的:

template <typename T>
T zero() { return 1; }

template <>
float zero<float>() { return 3.0f; }

struct Zero
{
    template<typename T>
    operator T()
    {
        return zero<T>();
    }
};

int main()
{
    int x = Zero();
    float y = Zero();
    return x + y;
}
Run Code Online (Sandbox Code Playgroud)

首先创建临时对象 Zero(),在赋值期间我们使用转换运算符来执行零模板函数的正确特化。