简体   繁体   English

在函数指针类型之间转换

[英]Converting between function pointer types

I have a program that has to store functions as void (*) (void*) . 我有一个程序,必须将函数存储为void (*) (void*) Creating functions with that signature leads to code duplication (usually the first line is to cast the void pointer to the correct type) and reduces type safety (the void pointer can be cast to anything, such as the wrong type), so I was wondering if I can take a function of type void (*)(T*) , and then convert it to a void(*)(void*) and call it like that, in a way similar to this: 使用该签名创建函数会导致代码重复(通常第一行是将void指针强制转换为正确的类型)并减少类型安全性(void指针可以转换为任何内容,例如错误的类型),所以我想知道如果我可以使用void (*)(T*)类型的函数,然后将其转换为void(*)(void*)并像这样调用它,方式类似于:

#include <iostream>
#include <string>

void printer(std::string* string)
{
    std::cout << *string << std::endl;
}

int main() 
{
    //Cast the function to a one that takes a void pointer
    auto func = reinterpret_cast<void(*)(void*)>(&printer);
    //Create a string and call the function with it
    std::string string = "Hello World";
    func(&string);
    return 0;
}

The above code compiles and runs fine (on ideone ) but I was wondering if it's at all standards compliant or if it's undefined behaviour and is just working correctly for my specific example and OS 上面的代码编译并运行良好(在ideone上 ),但我想知道它是否符合所有标准,或者它是否是未定义的行为,并且只是对我的具体示例和操作系统正常工作

This is undefined behavior. 这是未定义的行为。

[expr.call]/1: [expr.call] / 1:

Calling a function through an expression whose function type is different from the function type of the called function's definition results in undefined behavior. 通过函数类型与被调用函数定义的函数类型不同的表达式调用函数会导致未定义的行为。

[expr.reinterpret.cast]/6: [expr.reinterpret.cast] / 6:

A function pointer can be explicitly converted to a function pointer of a different type. 函数指针可以显式转换为不同类型的函数指针。 Except that converting a prvalue of type "pointer to T1 " to the type "pointer to T2 " (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. 除了将“指向T1指针”的prvalue转换为“指向T2指针”类型(其中T1T2是函数类型)并返回其原始类型产生原始指针值之外,这种指针转换的结果未指定。

C++ doesn't allow for very many function casts at all to work, even for things you might think would be safe like changing const details. C ++根本不允许很多函数转换工作,即使是你可能认为安全的事情就像更改const细节一样。 When you need such a thing, use an explicit wrapper function instead. 当您需要这样的东西时,请使用显式的包装函数。 A non-capturing lambda could be one easy way to write one without naming it; 非捕获lambda可以是一种简单的方法来编写一个而不命名它; or you could define a general template to wrap other functions in a way you need. 或者您可以定义一个通用模板,以您需要的方式包装其他功能。

[Strangely, C++17 allows an implicit conversion from a pointer to nonthrowing function to a pointer to potentially-throwing function even though C++17 makes those different function types - but then doesn't have any wording I can see saying you're allowed to actually call the function via that converted pointer.] [奇怪的是,C ++ 17允许从指针到非投掷函数的隐式转换到指向潜在抛出函数的指针,即使C ++ 17生成那些不同的函数类型 - 但是后来没有任何措辞我可以看到你说'允许通过转换后的指针实际调用该函数。

Behaviour of doing so is undefined. 这样做的行为是不确定的。 Standard (draft) says: 标准(草案)说:

[expr.reinterpret.cast] A function pointer can be explicitly converted to a function pointer of a different type. [expr.reinterpret.cast]函数指针可以显式转换为不同类型的函数指针。 [Note: The effect of calling a function through a pointer to a function type (9.2.3.5) that is not the same as the type used in the definition of the function is undefined. [注意:通过指向函数类型(9.2.3.5)的指针调用函数的效果与函数定义中使用的类型不同是未定义的。 — end note] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. - 结束注释除了将“指向T1的指针”类型的prvalue转换为“指向T2的指针”类型(其中T1和T2是函数类型)并返回其原始类型产生原始指针值,这样的结果指针转换未指定。 [Note: See also 7.3.11 for more details of pointer conversions. [注意:有关指针转换的更多详细信息,请参见7.3.11。 — end note] - 结束说明]


You could use a lambda: 你可以使用lambda:

void(*func)(void*) = [](void *string) {
    printer(static_cast<std::string*>(string));
};

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM