2017-08-31 7 views
1

コンパイル時にextern "C"関数と非[extern "C"]関数を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; 
} 

OS X上のプリントgccclangsame C++リンケージを持つC結合および機能を持つ

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

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

あなたのシステムに同じ呼び出し規約がありますか? –

+0

@VladimirBerezkin私はそれがシステムに依存するとは思わない。私はテンプレートが展開されるときに起こる動作について尋ねています...システム依存のものが実際に結果に影響を与えるチャンスを持つ前のものです。 –

+0

より正確には、ポインターを呼び出すときに使用されるもの以外の呼び出し規約のポインターを、そのようなポインターを取得するためにキャストせずに持つことができるかどうかです。いいえ。実際には、呼び出し規約はデフォルトではすべての既存のコンパイラと同じであるため、問題はかなり疑問です。 –

答えて

1

機能は、さまざまな種類があり、それらは同じ引数の型を取る場合でも、同じ型を返します。 (うーん、馴染み深い)。しかし、ほとんどのコンパイラはこのルールを強制せず、同じタイプとして扱います。 (うーん、馴染み深い)。

したがって、例えば、C++標準はstd::qsortが過負荷、C比較関数としての結合、比較関数としてC++リンケージを持つ関数を取る一つと機能を取る一つを有することを指定します。これは単純なオーバーロードであり、いずれの関数型でもstd::qsortを呼び出すと、コンパイラは適切なオーバーロードを選択することになっています。

はい、std::is_sameは、この2つのタイプを区別するために必要なものです。しかし、やはり、ほとんどのコンパイラはそれらを異なる型として扱っていません。それらのコンパイラの1つを持っているなら(そしてほとんど確実にそうします)、それらは同じ型を持ち、それらを区別することはできません。そのため、たとえば、これらのコンパイラの標準ライブラリには、のバージョンがstd::qsortしかありません。

+1

あなたは、彼らが異なるタイプを持っていることを言う標準からの通路を挙げることができますか? –

関連する問題