Что именно представляет параметр шаблона, передаваемый в шаблон std :: function? - PullRequest
3 голосов
/ 19 февраля 2020

std::function сама предлагает отличную утилиту - она ​​обеспечивает стирание типов для общего хранения / предоставления доступа к вызываемым объектам. Его гибкость велика:

#include <functional>
#include <iostream>

void printer() {
    std::cout << "I print!";
}

int adder(int a, int b) {
    return a + b;
}

int main() {
    std::function<void()> fun1 = printer;       // fun1() calls printer()
    std::function<int(int, int)> fun2 = adder;  // fun2(1, 2) calls adder(1, 2)

    std::function<void()> fun3 = [](){};        // fun3() will do nothing - same for the lambda
    std::function<int(int, int)> fun4 =
            [](int a, int b) { return a + b; }; // fun4(1, 2) will yield the sum
}

И, если честно, все имеет смысл. std::function<void()> говорит, что это function, который при вызове возвращает void и не принимает (()) аргументов. То же самое для std::function<int(int, int)> - при вызове он возвращает int и требует двух int s в качестве аргументов.

Хотя интуитивно, я считаю, что мне не хватает фундаментального понимания того, что именно есть явный параметр шаблона. Что именно является void() или int(int, int)? Они не могут быть указателями на функции, потому что когда я это делаю:

int main() {
    using type = void();

    type x = printer;
}

Я получаю следующее предупреждение и ошибку:

main.cpp:15:10: warning: declaration of 'void x()' has 'extern' and is initialized
 type x = printer;
      ^
main.cpp:15:14: error: function 'void x()' is initialized like a variable
 type x = printer;
          ^~~~~~~

Ну, очевидно, это выглядит так переменная - я хотел чтобы она была переменной. Однако, если бы я хотел указатель на функцию, мне пришлось бы делать:

using type = void(*)();

вместо:

using type = void();

Что именно является типом с опущенным *? Что именно представлено интуитивно понятными параметрами шаблона при использовании, например, с std::function?

Ответы [ 2 ]

5 голосов
/ 19 февраля 2020

Что именно за тип с пропущенным *?

Подумайте об этом. Тип, за которым следует «*», означает «указатель на этот тип». Если вы не «следите» за типом с *, тогда тип означает именно этот тип. Так что если у вас есть указатель на функцию, то это указатель на ... тип функции.

Следовательно, типы типа void() являются типами функций.

Типы функций отличаются от объектов типы, но они все еще являются типами. Таким образом, вы можете играть в большинство типовых игр с ними, что позволяет C ++. Но поскольку они не являются объектными типами, вы не можете создавать объекты функционального типа.

3 голосов
/ 19 февраля 2020

Что такое void() или int(int, int)?

Это функциональные типы. Например. если вы объявляете void foo(), тип foo равен void():

#include <type_traits>

int main() {
  static_assert(std::is_function_v<int(int, int)> &&
                std::is_function_v<void()> &&
                std::is_same_v<decltype(main), int()>);
}

LIVE

...