C++14 auto deduction error: function returns an array

C++14 auto deduction error: function returns an array

社区! 我正在尝试应用新的 C++14 功能,但在尝试将 const char[] 参数传递给下面给出的函数时意外遇到错误:

 decltype(auto) autofunc( const auto& a)
 {
     cout<<"Hello World\n";
     cout<<a<<endl;

 }


 auto lambd = [](const auto& word){  autofunc(std::forward< decltype(word) > (word));};

int main()
{


 lambd("Goodbye World\n");


    return 0;
}

我不知道为什么,但编译器的消息是该函数试图 return 一个数组(它为什么要这样做?)。如果我将函数的 return 类型更改为 void 它将被编译。如果我传递另一种类型的参数(不是数组),它将被编译。数组有什么问题?

错误信息

../../untitled6/main.cpp: In instantiation of '<lambda(const auto:3&)> [with auto:3 = char [15]]':
../../untitled6/main.cpp:74:25:   required from here
../../untitled6/main.cpp:68:84: error: no matching function for call to 'autofunc(const char [15])'
  auto lambd = [](const auto& word){  autofunc(std::forward< decltype(word) > (word));};
                                                                                    ^
../../untitled6/main.cpp:68:84: note: candidate is:
../../untitled6/main.cpp:60:17: note: template<class auto:2> decltype(auto) autofunc(const auto:2&)
  decltype(auto) autofunc( const auto& a)
                 ^
../../untitled6/main.cpp:60:17: note:   template argument deduction/substitution failed:
../../untitled6/main.cpp: In substitution of 'template<class auto:2> decltype(auto) autofunc(const auto:2&) [with auto:2 = char [15]]':
../../untitled6/main.cpp:68:84:   required from '<lambda(const auto:3&)> [with auto:3 = char [15]]'
../../untitled6/main.cpp:74:25:   required from here
../../untitled6/main.cpp:60:17: error: function returning an array
error: no matching function for call to 'func(const char [15])'
  auto lambd = [](const auto& word){  func(word);};
                                               ^
note: candidate is:

template<class auto:1> 
decltype(auto) func(const auto:1&)

decltype(auto) func( const auto& a)
            ^

是您遇到的错误。它说 return 类型与参数相同。那是因为你有 decltype(auto) 并且实现将 "func" 替换为:

template<class T>
T func(const T& a)

而不是:

template<class T, class R>
R func(const T& a);

我不知道它为什么这样做..但错误本身很清楚。

这很好用:

#include <iostream>

using namespace std;

decltype(auto) func(const auto &a)
{
     cout<<"Hello World\n";
     cout<<a<<endl;
}


 auto lambd = [](const auto word){  func(std::forward<decltype(word)>(word));};

int main()
{
    lambd("Goodbye World\n");
    return 0;
}

一旦你把它变成const reference,它就不起作用了。我还不知道为什么。

编辑:

我让它工作的唯一方法是:

#include <iostream>

using namespace std;

decltype(auto) func(const auto &a)
{
     cout<<"Hello World\n";
     cout<<a<<endl;
}


 auto lambd = [](const auto &word){  func(std::forward<decltype(word)>(word));};

int main()
{
    lambd((const char*)"Goodbye World\n");   
    return 0;
}

也就是为字符串创建一个临时变量并传递它。或者将参数转换为指向 char 数组的指针。好像很难判断是"const char[15]"还是"const char*".

无论哪种方式,上面的方法都有效。

这是一个 GCC 错误。

auto 在 C++14 的函数参数声明中是不允许的。此语法由 Concepts Lite TS 添加。 GCC 4.9 release notes

G++ supports unconstrained generic functions as specified by §4.1.2 and §5.1.1 of N3889: Concepts Lite Specification. Briefly, auto may be used as a type-specifier in a parameter declaration of any function declarator in order to introduce an implicit function template parameter, akin to generic lambdas.

N3889 是概念 TS 的早期工作草案。引用的部分 5.1.1 部分内容为

A generic function is denoted by function declarator having auto or a concept-name as part of the type-specifier in its parameter-declaration-clause. [Example:

auto f(auto x); // Ok
void sort(Sortable& c); // Ok (assuming Sortable names a concept)

end example ]

The use of auto or a concept-name in the parameter-declaration-clause shall be interpreted as the use of a type-parameter having the same constraints and the named concept. [ Note: The exact mechanism for achieving this is unspecified. — end note ] [Example: The generic function declared below

auto f(auto x, const Regular& y);

Is equivalent to the following declaration

template<typename T1, Regular T2>
auto f(T1 x, const T2&);

end example ]

请注意,此转换不应影响 return 类型;它仍然是 auto - 这意味着它将被推导。

根据这些规则,autofunc 的声明应该等同于

template<class T>
decltype(auto) autofunc( const T& a) { /* ... */ }

这本来是有效的。相反,它被解释为

template<class T>
T autofunc( const T& a) { /* ... */ }

导致错误,因为在您进行的所有转发中,T 最终被推断为数组类型。

这特别具有讽刺意味,因为 GCC 4.9 自己的注释(上面引用的)说

// the following two function declarations are equivalent
auto incr(auto x) { return x++; }
template <typename T>
auto incr(T x) { return x++; }

在 GCC 4.9 上是 demonstrably not the case