Reputation: 10527
I've got a quick sample:
#include <utility>
using namespace std;
struct A{
int i;
char c;
};
void f(const A&){}
template<class T>
void g(T&& t)
{
f(forward<T>(t));
}
int main() {
A a={1,'@'};//OK
f({1,'#'});//OK
g({1,'@'});//Compilation error
return 0;
}
Clang will give this error:
testArray.cpp:16:5: error: no matching function for call to 'g' g({1,'@'});//fix: g<A>({1,'@'}) ^ testArray.cpp:9:6: note: candidate template ignored: couldn't infer template argument 'T' void g(T&& t) ^
My questions are:
In A a={1,'@'};
, if {}
is deduced as std::initializer_list
, then how is it converted from std::initilizer_list
to type A
?
In f({1,'#'});
, when f
requires a type A
, does the compiler implicitly generate an A
object, or does it convert from std::initializer_list
to A
?
why, when g()
is a template, does the template type deduction not work to give a type A
? Does std::forward
help to convey the message from f
to g
, say that T
is type A
?
Upvotes: 2
Views: 105
Reputation: 172984
- In 'A a={1,'@'}'' :If {} is deduced as std::initializer_list, then how it's converted from std::initilizer_list to type A?
No, it has nothing to do with std::initializer_list
. a
is just copy-list-initialized from {1,'@'}
.
- In 'f({1,'#'});' When f requires a type A, does compiler implicitly generates an A object, or it converts from std::initializer_list to A?
It still has nothing to do with std::initializer_list
. The function parameter is copy-list-initialized from {1,'#'}
.
- why when "g()" is a template, the template type deduction doesn't work to give a type A? Does "forward" help to convey the message from f to g, say that T is type A()?
Because this belongs to non deduced context, the template parameter T
can't be deduced and cause the compile error.
6) The parameter P, whose A is a braced-init-list, but P is not std::initializer_list or a reference to one:
And
when does compiler consider {} as std::initializer_list, and when doesn't?
When you declare the funciton parameter type as std::initializer_list
and you pass a braced list as argument, then std::initializer_list
will be constructed. Another case is for auto
, e.g.
auto x1 = {3}; // x1 is deduced as std::initializer_list<int>
auto x2{1, 2}; // after C++17, error: not a single element
// before C++17, it was std::initializer_list<int>
auto x3{3}; // after C++17, x3 is deduces as int
// before C++17 it was std::initializer_list<int>
BTW: Even with auto
it won't work for {1,'@'}
, should it be std::initializer_list<char>
, or std::initializer_list<int>
?
Upvotes: 3