问题
community! I'm trying to apply new C++14 features and unexpectedly encountered on error while I was attempting to pass the const char[] argument to the function given below:
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;
}
I don't know why,but the compilier's message is that function tries to return an array (why would it do this?). If I change function's return type to void It'll be compiled. If I pass an argument of another type(not array) It will be compiled. What is the problem with arrays?
Error message
../../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
回答1:
This is a GCC bug.
auto is not allowed in function parameter declarations in C++14. This syntax is added by the Concepts Lite TS. The GCC 4.9 release notes say that
G++ supports unconstrained generic functions as specified by §4.1.2 and §5.1.1 of N3889: Concepts Lite Specification. Briefly,
automay 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 is an early working draft of the concepts TS. The cited section, 5.1.1, reads in part
A generic function is denoted by function declarator having
autoor 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
autoor 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 belowauto 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 ]
Note that this transformation is not supposed to affect the return type; it remains auto - meaning that it will be deduced.
Given these rules, autofunc's declaration should have been equivalent to
template<class T>
decltype(auto) autofunc( const T& a) { /* ... */ }
which would have been valid. Instead, it got interpreted as
template<class T>
T autofunc( const T& a) { /* ... */ }
causing an error since, with all the forwarding you are doing, T ends up getting deduced as an array type.
This is particular ironic since GCC 4.9's own notes (cited above) say that
// the following two function declarations are equivalent auto incr(auto x) { return x++; } template <typename T> auto incr(T x) { return x++; }
which is demonstrably not the case on GCC 4.9.
回答2:
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)
^
Is the error you're getting. It says the return type is the same as the parameter. That's because you have decltype(auto) and the implementation replaces the "func" with:
template<class T>
T func(const T& a)
instead of:
template<class T, class R>
R func(const T& a);
I don't have an explanation why it does this.. but the error itself is clear.
This works fine:
#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;
}
As soon as you make it a const reference, it will not work. I still don't know why yet.
EDIT:
The only way I can get it working at all is to do:
#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;
}
Aka creating a temporary variable for the string and passing that instead.. OR casting the parameter to a pointer to a char array. It seems that it has a hard time telling whether it is a "const char[15]" or "const char*".
Either way, the above will work.
来源:https://stackoverflow.com/questions/28380494/c14-auto-deduction-error-function-returns-an-array