是否允许占位符作为函数模板返回类型?

The*_*ind 3 c++ clang visual-c++

考虑以下模板及其专业化:

template<typename R>
R func() {
    return 0;
}

template<>
auto func() {
    std::cout << "Auto deduced" << std::endl;
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

我不确定是否允许这样的声明,但是当使用 Xcode 编译它时,clang 会发出一个奇怪的错误:

template<typename R>
R func() {
    return 0;
}

template<>
auto func() {
    std::cout << "Auto deduced" << std::endl;
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

尽管无法调用专业化,MSVC 仍然可以很好地编译它。是否允许这种专业化?如果允许,如何使用它?

The*_*ind 5

[dcl.spec.auto.general]/13提供以下详细信息:

具有使用占位符类型的声明返回类型的函数或函数模板的重新声明或特化也应使用该占位符,而不是推导类型。同样,具有不使用占位符类型的已声明返回类型的函数或函数模板的重新声明或特化不应使用占位符。

换句话说,任何不使用占位符返回类型的函数模板(即使它是模板参数)都不能专用于占位符返回类型:

template<typename R>
R func() { return 0; }

template<>
int func() { return 1; } // OK

template<>
auto func() { return "str"; } // Error. Redeclaration
Run Code Online (Sandbox Code Playgroud)

同样,任何使用占位符返回类型的模板只能使用占位符返回类型进行专门化:

template<typename R>
auto func(R arg) { return arg; }

template<>
auto func(int arg) { return arg; } // OK

template<>
float func(float arg) { return arg; } // Error. Redeclaration
Run Code Online (Sandbox Code Playgroud)

对于 clang 来说,这是一个编译器错误,MSVC 接受它是错误的,只有GCC 按预期拒绝它

<source>:9:6: error: template-id 'func<>' for 'auto func()' does not match any template declaration
    9 | auto func() {
      |      ^~~~
<source>:4:3: note: candidate is: 'template<class R> R func()'
    4 | R func() {
      |   ^~~~
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)