【问题标题】:What exactly is represented by the template parameter passed to std::function template?传递给 std::function 模板的模板参数究竟代表什么?
【发布时间】:2020-02-19 15:47:03
【问题描述】:

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&lt;void()&gt; 表示它是一个 function,它在调用时返回 void 并且不接受 (()) 参数。 std::function&lt;int(int, int)&gt; 同上 - 调用时,它返回一个 int 并需要两个 ints 作为其参数。

虽然直观,但我相信我缺乏对 显式模板参数的基本理解。 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 等一起使用时,直观的显式模板参数究竟代表了什么?

【问题讨论】:

  • 嗯,它是……一个函数。
  • int(int) 是一种类型。 int foo(int) 是该类型的可能函数。 int(*)(int) 是指向该类型的指针。函数有自己的类型,就像对象一样。
  • @Quentin 好吧,这既非常具体又非常不具体。如果它是一个函数,我可以声明它吗?我可以稍后定义它吗?我可以声明和定义它吗?围绕它的规则是什么?描述围绕它的行为的标准的相关部分是什么?我很高兴阅读:>
  • 请注意type * x = &amp;printer; 有效的。
  • @Caleth 非常有用的评论 - 它确实对类型系统有所启发,谢谢!

标签: c++ function-pointers std-function


【解决方案1】:

省略 * 的类型到底是什么?

考虑一下。 “后跟”* 的类型表示“指向该类型的指针”。如果您没有使用*“关注”一个类型,那么该类型就意味着该类型。所以如果你有一个函数指针,那么它就是一个指向...函数类型的指针。

因此,像void() 这样的类型是函数类型。

函数类型不同于对象类型,但它们仍然是类型。因此,您可以使用它们玩 C++ 允许的大多数基于类型的游戏。但由于它们不是对象类型,所以不能创建函数类型的对象。

【讨论】:

  • @HTNW 这听起来像是为了std::function而将这种类型放入语言中。
  • @HTNW:这是一个实现细节,与“那是什么类型?”的问题无关,
  • @Fureeish 这并不是一个真正的特殊语法,可能只是使用频率较低。有各种各样的类型不兼容并且使用不同的表示法,包括成员指针和成员函数指针。没有一个或多或少是特别的,尽管可能不太常用。
  • @HTNW 我同意这个问题似乎与std::function 的工作方式无关,我相信它只是使用std::function 作为函数类型的用例示例来更好地说明在问什么。在我看来,这个问题是关于什么是函数类型。无论如何,std::function 如何存储它是可调用的东西并不会真正影响它在概念上的思考方式。正如 Nicol Bolas 所说,这是一个实现细节。
  • @Fureeish 更准确地说,括号不会像在数学表达式中那样对术语进行“分组”。此处使用它们的方式与声明或调用函数时相同,用于分隔函数参数列表。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 2021-10-30
    相关资源
    最近更新 更多