слишком много аргументов для функции std :: make_shared <vector> - PullRequest
5 голосов
/ 06 апреля 2020

Я что-то упустил с std::make_shared. Разве он не может разрешить тип std::initializer_list, или я делаю что-то еще неправильно?

#include <vector>
#include <memory>

class A {};

int main()
{
    A a;
    std::vector<A> veca{A(), A{}, a}; // this works ofc
    std::vector<A> vecb({A(), A{}, a}); // this too

    std::make_shared<std::vector<A>>(vecb); // and this, ofc
    std::make_shared<std::vector<A>>({a}); // what's wrong here?
    return 0;
}

Ошибка:

main.cpp:21:41: error: too many arguments to function ‘std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = std::vector; _Args = {}]’
     std::make_shared<std::vector<A>>({a});
                                         ^
In file included from /usr/include/c++/6/memory:82:0,
                 from main.cpp:10:
/usr/include/c++/6/bits/shared_ptr.h:632:5: note: declared here
     make_shared(_Args&&... __args)
     ^~~~~~~~~~~

Живой пример: https://onlinegdb.com/r1DlHquDL

1 Ответ

2 голосов
/ 06 апреля 2020

Рассмотрим следующий минимальный пример вашей проблемы:

template <typename... Ts>
void f(Ts&&...);  // replacement for std::make_shared

int main()
{  
  f({1});
}

Этот случай описан в стандарте C ++ в [temp.deduct.call/1] :

Вывод аргумента шаблона выполняется путем сравнения каждого типа параметра шаблона функции (назовите его P), который содержит параметры шаблона, которые участвуют в выводе аргумента шаблона, с типом соответствующего аргумента вызова (назовите его A) как описано ниже. Если удаление ссылок и квалификаторов cv из P дает std::initializer_list<P′> или P′[N] для некоторых P′ и N, а аргумент является непустым списком инициализатора ([dcl.init.list]), то вычет вместо этого выполняется независимо для каждого элемента списка инициализатора, принимая P′ в качестве отдельных типов параметров шаблона функции P′i и i элемент инициализатора в качестве соответствующего аргумента. В случае P′[N], если N является нетиповым параметром шаблона, N выводится из длины списка инициализатора. В противном случае, аргумент списка инициализатора приводит к тому, что параметр считается неделедированным контекстом ([temp.deduct.type]).

В вашем случае применяется последнее предложение , Интересно, что сообщение об ошибке говорит что-то еще с G CC, что странно. С Clang сообщение об ошибке ясно:

error: no matching function for call to 'f'

note: candidate template ignored: substitution failure: deduced incomplete pack <(no value)> for template parameter 'Ts'

...