2017-08-31 67 views
1

编译时是否可以在C++中区分extern "C"函数和非[extern "C"]函数?C++:是否可以区分extern“C”函数和普通函数?

他们有非常不同的行为,显然,允许有不同的调用约定(请参阅https://stackoverflow.com/a/45968482/931154)。

以下代码片段表明,使用编译时可用的信息无法区分它们。

#include <iostream> 
#include <type_traits> 

int cpp_add(int x, int y) { return x + y; } 

extern "C" int c_add(int x, int y) { return x + y; } 

typedef decltype(cpp_add) cpp_t; 
typedef decltype(c_add) c_t; 

constexpr bool sameness = std::is_same<cpp_t, c_t>::value; 

int main(int argc, char *argv[]) { 
    if (sameness) 
    std::cout << "same" << std::endl; 
    else 
    std::cout << "different" << std::endl; 
    return 0; 
} 

打印samegccclang在OS X

% g++ --std=c++11 externcsame.cpp && ./a.out 
same 

% clang++ --std=c++11 externcsame.cpp && ./a.out 
same 
+0

可能在您的系统上它们具有相同的调用约定? –

+0

@VladimirBerezkin我不认为这是依赖于系统的。我问的是扩展模板时发生的行为......这是在系统相关的东西真正有机会影响结果之前发生的。 –

+0

更准确地说,问题是您是否可以拥有一个指向调用约定的函数的指针,而不是通过指针调用时使用的指针,而不用强制转换以获取此类指针?不,并且在实践中,默认情况下调用约定是相同的,对于所有现存的编译器,这个问题是相当有限的。 –

回答

1

C链接函数和功能与C++联动有不同的类型,即使它们采取相同的参数类型和返回相同类型。 (嗯,听起来很熟悉)。但大多数编译器不强制执行此规则,并将它们视为相同类型。 (嗯,听起来很熟悉)。

因此,例如,C++标准指定std::qsort具有重载,一种采用C链接作为比较功能,和一个接受一个函数与C++联动作为比较功能的功能。这只是简单的重载,当你用任一函数类型调用std::qsort时,编译器应该选择适当的过载。

所以,是的,std::is_same应该是你需要区分这两种类型。但是,大多数编译器不会将它们视为不同的类型。如果你有一个编译器(你几乎肯定会这样做),那么它们的类型是相同的,你不能将它们分开。因此,例如,这些编译器的标准库只有一个版本的std::qsort

+1

你能否引用标准中的说法,说他们有不同的类型? –

相关问题