简体   繁体   English

在一行中声明和定义函数指针变量

[英]declare and define function pointer variable in one line

In C++ how do we do the following 在C ++中我们如何执行以下操作

// fundamental language construct        
   type name = value ; 
// for example 
   int x = y;

with function pointers? 用函数指针?

 typedef (char)(*FP)(unsigned);

 // AFAIK not possible in C++
 FP x = y ;

I can use lambdas: 我可以用lambdas:

 FP x = []( unsigned k) -> char { return char(k); }

But I do not know how to do this without lambda. 但我不知道如何在没有lambda的情况下做到这一点。 Any ideas? 有任何想法吗?

Whenever you can write a typedef, you can also write a variable declaration with no typedef, with almost identical syntax. 每当你可以编写一个typedef时,你也可以编写一个没有typedef的变量声明,语法几乎相同。

Example: 例:

 // typedef
 typedef char(*FP)(unsigned);
 FP x = y ;

 // no typedef
 char(*x)(unsigned) = y;

Remove the typedef keyword, and you have a variable declaration. 删除typedef关键字,并且您有一个变量声明。 Slap an initialisation on it if you want. 如果你愿意,可以对其进行初始化。

You can use auto : 你可以使用auto

auto fptr = &f;

It skips the need of a typedef and conserve a nice syntax. 它省略了typedef的需要并保留了一个很好的语法。

It is almost the same as Lambdas, but hard to read i think: 它几乎和Lambdas一样,但我觉得很难读:

void my_int_func(int x)
{
    std::cout << "ther param is: " << x << std::endl;
}

//
int main(int argc, char *argv[])
{
    void (*foo)(int) = my_int_func;
    foo(1);

But I do not know how to do this without lambda. 但我不知道如何在没有lambda的情况下做到这一点。 Any ideas? 有任何想法吗?

Just dont use a lambda but a function: 只是不要使用lambda但功能:

typedef char(*FP)(unsigned);   

char foo(unsigned){ return 0;}

int main() {
    FP x = foo;
}

Function pointer typedefs are rather nasty, if you can better use using : 函数指针的类型定义是相当恶劣的,如果你能更好的利用using

using FP = char(*)(unsigned);

Live Demo 现场演示

Well... if you're using lambdas, you can also use auto , so 好吧......如果你使用lambdas,你也可以使用auto ,所以

auto x = foo;

The following is a full compiling example with a static_assert() that verify the obtained type 以下是一个完整的编译示例,其中包含一个static_assert() ,用于验证获取的类型

#include <type_traits>

char foo (unsigned)
 { return ' '; }

int main ()
 {
   auto x = foo;

   static_assert( std::is_same<decltype(x), char(*)(unsigned)>::value, "!" );
 }

Using auto with lambda in the way you used it with FP 使用auto与lambda一起使用它与FP

auto y = []() ->bool { return true; };

leads to something different: the type of y above is an unnamed class with an operator() , not a function pointer type to that operator() . 导致不同的东西:类型y以上是与一个未命名的类operator()而不是一个函数指针类型到operator()

If you want a pointer to function, you have to convert the lambda to it using the operator + , as you can verify with the following static_assert() 如果你想要一个指向函数的指针,你必须使用operator +将lambda转换为它,因为你可以使用以下static_assert()验证

auto y = +[]() ->bool { return true; };

static_assert( std::is_same<decltype(y), bool(*)()>::value, "!" );

Many thanks all for the lively roller-coaster of useful comments. 非常感谢所有人提供有用评论的热闹过山车。 Somebody on Reddit, where I asked the same question, under the user name "TheTiefMaster", dropped this "one liner": Reddit上有人在用户名“TheTiefMaster”下问了同样的问题,放弃了这个“一个班轮”:

// also works as C
char whatever(unsigned k) { return char(k); } char(*F)(unsigned) = whatever;

Let me clarify: I do understand these are two statements on one line. 让我澄清一下:我确实理解这些是一行中的两个陈述。 And no there is no type in here, but one function pointer pointing to the same function. 并且这里没有类型,但是一个函数指针指向同一个函数。 The usage: 用法:

    auto x = whatever(65); // 'A'
    auto y = F(66); // 'B'

Then I figured the following will make the function definition and its type declaration: 然后我想到以下将进行函数定义及其类型声明:

    // FP is a type of function whoever
    char whoever(unsigned k) { return 'A'; } typedef char(*FP)(unsigned) ;

Calling whoever behaves as expected 呼叫任何表现如预期的人

   auto w = whoever(42) ; // 'A'

FP is where it starts getting interesting. FP是它开始变得有趣的地方。 FP is a type, and as it turns out one can cast to the type. FP是一种类型,事实证明,可以转换为类型。

     // using FP as a type
     // c++ style type cast
     // empty cast returns nullptr
     auto fun = FP();
     // calling fun() above crashes
     // but it is "invocable" as per C++ rules
     static_assert(std::is_invocable_v<P2F()>);

Passing any argument to this cast, works and returns non null address: 将任何参数传递给此强制转换,工作并返回非null地址:

      // update: this compiles only on MSVC
      // and is a bug
      auto fun = FP(42); 
      // type of fun is char (*) (unsigned)

Calling the result of this fun crashes, obviously: 显然,召唤这个有趣的崩溃的结果:

     // reading access violation
     fun(123) ;

This cast with an instance from any required function, works: 使用任何所需函数的实例进行此转换,有效:

    auto fun = FP(whatever); 

    // works, obviously
    fun(65) ; // 'A'

To use this knowledge we will use the static_cast to safely cast to what we can call. 要使用这些知识,我们将使用static_cast安全地转换为我们可以调用的内容。 C++ type cast is too forceful, just like C style type cast is. C ++类型转换太强大了,就像C风格类型转换一样。

     // does not compile
     // fun is the wrong type and can not be called
     auto fun = static_cast<FP>(42); 

     // does compile, fun is safe to call
         auto fun = static_cast<FP>(whatever);

    // works, obviously
    fun(65) ; // 'A'

This investigation is obviously far from over. 这项调查显然远没有结束。 I shall proceed with it, elsewhere. 我将在其他地方继续进行。

Update: 更新:

       using FP = char (*)(int) ;
       // must not compile, compiles under MSVC
       auto oops = FP(42) ;

Is the bug in MSVC, I reported it today. 是MSVC中的错误,我今天报道了。

The code: 编码:

typedef char(*FP)(int);
FP x = y;

fails to compile with current C++ compilers if y is a lambda expression capturing a variable. 如果y是捕获变量的lambda表达式,则无法使用当前的C ++编译器进行编译。

// Compiles OK
FP x0 = [](int k) -> char { return char(k); };

// Fails to compile
int i = 123;
FP x1 = [=](int k) -> char { return char(k); };
FP x2 = [=](int k) -> char { return char(k+i); };
FP x3 = [&](int k) -> char { return char(k+i); };
FP x4 = [i](int k) -> char { return char(k+i); };
// error: cannot convert ‘main()::<lambda(int)>’ to ‘FP {aka char (*)(int)}’
//        in initialization

The reason why it fails to compile is that the size of the right side of the assignment to x1 ... x4 is greater than size of FP . 它编译失败的原因是x1 ... x4赋值右侧的大小大于FP大小。

For a C++ compiler to make assignments to x1 ... x4 be valid it would need to generate code at runtime. 对于使x1 ... x4赋值有效的C ++编译器,它需要在运行时生成代码。 Current C++ compilers such as GCC and clang do not support this, mainly because it would cause memory leaks because C++ isn't a garbage collected language. 当前的C ++编译器(如GCC和clang)不支持这一点,主要是因为它会导致内存泄漏,因为C ++不是垃圾收集语言。 Some garbage collected language implementations, such as earlier versions of the official Go compiler, do support such assignments by performing runtime code generation. 一些垃圾收集的语言实现,例如官方Go编译器的早期版本,通过执行运行时代码生成来支持这样的分配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在一行中声明并初始化指向类实例的指针 - Declare and initialize pointer to a class instance in one line C ++ typedef函数指针,并在一条语句中声明一个指针 - C++ typedef function pointer and declare a pointer in one statement 可以在C / C ++中声明但不能定义局部变量吗? - Can one declare but not define local variable in C/C++? 在命名空间中声明和定义函数? - Declare and Define a Function in a Namespace? 无法在成员函数本身中声明派生的数据类型指针变量 - Not able to declare a derived datatype pointer variable in member function itself 如何在C ++中将指向变量的指针声明为函数的参数? - How to declare a pointer to a variable as a parameter of a function in C++? 如何声明/定义一个 function 与给定的 function 指针具有相同的返回和参数类型? - How to declare/define a function with the same return and parameter types as a given function pointer? 如何声明静态变量但不定义它 - How to declare a static variable but not define it 声明但不定义未使用的函数是否合法? - Is it legal to declare but not define a function that is unused? 声明具有默认指针值的函数 - Declare a function with default pointer value
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM