‒ Ты понимаешь, что происходит?
‒ Тебе объяснить?
‒ Объяснить я и сам могу... Ты понимаешь или нет?
Простите за эпиграф, но... Что-то у меня ощущение, что я могу объяснить, но не понимаю (или наоборот...), что происходит вот тут:
std::vector
Как стандарт трактует эти три выражения, и почему такой странный диагноз
emplace_back: функция не принимает 1 аргументов
у средней строки?
Ответ
Для этого предложения
v.emplace_back({1});
проблема состоит в том, что когда используются шаблонные параметры, то не выводится тип шаблонного параметра из заключенного в фигурные скобки аргумента. А функция emplace_back использует шаблонные параметы.
Из стандарта C++ (14.8.2.1 Deducing template arguments from a function call)
1 Template argument deduction is done by comparing each function
template parameter type (call it P) with the type of the corresponding
argument of the call (call it A) as described below. If removing
references and cv-qualifiers from P gives std::initializer_list
for some P0 and the argument is an initializer list (8.5.4), then
deduction is performed instead for each element of the initializer
list, taking P0 as a function template parameter type and the
initializer element as its argument. Otherwise, an initializer list
argument causes the parameter to be considered a non-deduced context
Можно смоделировать такую же ошибку следующим примером объявления класса
#include
struct A
{
template
int main()
{
A().f( { 1 } );
return 0;
}
Компилятор может выдать следующее диагностическое сообщение
prog.cpp: In function 'int main()':
prog.cpp:13:15: error: no matching function for call to 'A::f(
Если вы замените emplace_back на нешаблонный метод push_back , то соответствующий вызов будет компилироваться, так как тип параметра функции известен из типа объявленного инстанциированного вектора и представляет собой тип int
Поэтому вам явно нужно будет указать тип шаблонного аргумента функции
Например,
#include
struct A
{
template
int main()
{
A().f
return 0;
}
Или для emplace_back
#include
int main()
{
std::vector
v.emplace_back
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
Вывод программы на консоль
1
или для примера, предложенного @alexolut в комментарии
#include
struct S
{
S(std::initializer_list
int main()
{
std::vector v;
v.emplace_back
Что касается выражения в данном вызове
v.emplace_back(int{1});
то здесь используется явное преобразование типов, так называемая функциональная нотация.
Из стандарта C++ (5.2.3 Explicit type conversion (functional notation))
3 Similarly, a simple-type-specifier or typename-specifier followed by
a braced-init-list creates a temporary object of the specified type
direct-list-initialized (8.5.4) with the specified braced-init-list,
and its value is that temporary object as a prvalue.
Комментариев нет:
Отправить комментарий