Может кто-нибудь объяснить специальный синтаксис списка параметров шаблона std :: function (этот странный тип (типы ...))? - PullRequest
0 голосов
/ 24 января 2019

Может кто-нибудь объяснить специальный синтаксис std::function (этот странный Type(Types...))? Что это за скобки?Я знаю, что то, что находится внутри, означает список аргументов функции.

Мне просто интересно, что означает этот синтаксис.

//What am I doing? Can someone explain?

std::vector<int>      a; // 
std::vector<int(int)> b; // it counts as a type

//or
std::tuple<double, double> t1{0.0, 0.0}; // okey
std::tuple<double(double)> t2{0.0, 0.0}; // not okey, not the same as above(please explain what happens)

Ответы [ 3 ]

0 голосов
/ 24 января 2019

Когда вы объявляете функцию в C ++, вы используете практически такой же синтаксис

return_type function_name(parameter_type1, parameter_type2 /* and so on */)

Надеюсь, вы не найдете это странным.В синтаксисе объявления функции круглые скобки окружают список параметров.

Теперь, если вы удалите function_name из этого синтаксиса, у вас останется только сам тип функции, «извлеченный» из этого объявления

return_type (parameter_type1, parameter_type2)

Вот как вы описываете обычный тип функции в C ++.На самом деле, он унаследован непосредственно от C. Ничего нового, странного или необычного в этом нет.

В другом примере, когда вы объявляете

int a[10];

, вы фактически объявляете имя a какимеющий тип int [10].Точно так же, когда вы объявляете

double a(double);

, вы фактически объявляете имя a как имеющее тип double (double).

И вы не можете использовать тип функции в качестве типа элемента контейнера или типа кортежа.Тип функции не тип объекта .И эти контексты действительно требуют типов объектов.

Но вы можете (и у вас есть) использовать его в качестве аргумента шаблона для std::function.

0 голосов
/ 24 января 2019

Type(Types...) - это , а не «специальный синтаксис».Причина, по которой std::function принимает R(Args...), заключается в том, что он специализируется на типе функции R(Args...).Вот его декларация из стандарта:

template<class> class function; // undefined
template<class R, class... ArgTypes> class function<R(ArgTypes...)>;

Важно понимать, что синтаксис R(ArgTypes...) определяет тип функции.Если вы объявите функцию, такую ​​как int foo(int arg), тип foo будет int(int).

Вы можете создать свои собственные структуры, которые принимают аргументы таким образом:

template <class>
struct X;

template <class R, class ...Args>
struct X<R(Args...)> {
   typedef R result_type;
   // ... whatever
};

Причина, по которой вы не можете использовать int(int) с std::vector или std::tuple, заключается в их объявлениях:

template<class T, class Allocator = allocator<T>> class vector;
template<class... Types> class tuple;

Когда вы делаете std::vector<int(int)>, вы заменяете T на int(int), который не будет работать, потому что построение std::allocator<int(int)> не удастся (вы не можете выделить типы функций).

Когда вы делаете std::tuple<int(int)>, вы передаете int(int) в качестве первого типа в пакете параметров Types, который также не будет работать, потому что вы не можете иметь типы функций в качестве члена данных.

0 голосов
/ 24 января 2019

Вы не можете иметь тип функции в качестве параметра шаблона для std::vector (или std::tuple), но вы можете иметь функцию pointer type в этой роли.Например,

int foo(int x) { return 2 * x; }
int bar(int x) { return 3 * x; }

std::vector<int(*)(int)> v{&foo, &bar}; // & is optional here
std::cout << v[0](5); // Calls foo(5), outputs 10
std::cout << v[1](5); // Calls bar(5), outputs 15
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...