2016-08-01 19 views
3

で変数名を取得するための標準的な方法はと同様の挙動を達成するためのC++ 11以上で、いくつかの方法がありコンパイル時

some_intは

もしそうでなければ、それを行うコンパイラ固有の方法はありますか?私はMSVSをターゲットにしています。

+1

あなたが求める機能のための本当のユースケースを提供することはできますか?この例では 'std :: string x =" some_int ";と書くことができます。 – Leon

+4

マクロについて気にしないなら、[preprocessor's stringification](https://gcc.gnu.org/onlinedocs/cpp)を使うことができます/Stringification.html#Stringification) – wasthishelpful

+1

makro '#define NAME(VAR)#VAR'を使用できます。 'NAME(123) - >" 123 "' – Albjenow

答えて

7

あなたが尋ねる:あるべき

int some_int; 
std::string x=type_name<some_int>::value; //Theoretical code 
std::cout << x; 

結果:

と同様の挙動を達成するためのC++ 11以上で、いくつかの方法があり

some_intが

はい、あなただけの #プリプロセッサの 文字列化演算子を使用することができ

:この1つは、今回答されているので、

#include <iostream> 

#define NAME_OF(v) #v 

using namespace std; 
auto main() -> int 
{ 
    int some_int; 
    //std::string x=type_name<some_int>::value; //Theoretical code 
    auto x = NAME_OF(some_int); 
    (void) some_int; 
    cout << x << endl; 
} 

あなたが別の何かを求めている場合は、新しい質問を投稿してください(質問は考え改正しますこの回答を無効にする)。一例として、


現実世界用法が、ここではテスト関数に変数とその名を渡すことがマクロだ:

#define TEST(v) test(v, #v) 

あなたはコンパイル時のチェックをしたい場合はこと問題の名前は変数またはタイプ名です。次にsizeof、たとえばコンマ式に:

#define NAME_OF(v) (sizeof(v), #v) 

sizeofかを持つとの違い、これはおそらくも、実行時に何かをするコードを生成する対、コンパイル時に純粋に行われることが保証されているかどうかです。

#define NAME_OF(v) ((void) sizeof(v), #v) 

そして、あなたがtypeid追加できる関数名のためにも、この仕事をするために:

#define NAME_OF(name) ((void) sizeof(typeid(name)), #name) 

コンプリートを

あなたはvoidに擬似的なキャストを追加することができます可能な警告を回避するために、例:

#include <typeinfo> 

#define NAME_OF(name) ((void) sizeof(typeid(name)), #name) 

void foo() {} 

#include <iostream> 
using namespace std; 
auto main() -> int 
{ 
    int some_int; 
    (void) some_int; 
    //std::string x=type_name<some_int>::value; //Theoretical code 
    auto v = NAME_OF(some_int); 
    auto t = NAME_OF(int); 
    auto f = NAME_OF(foo); 
    #ifdef TEST_CHECKING 
     (void) NAME_OF(not_defined); 
    #endif 
    cout << v << ' ' << t << ' ' << f << endl; 
} 

チェックは100%perfではありませんただし、NAME_OFマクロに関数呼び出しを渡すことはまだ可能です。

+1

基本的に、あなたは「名前をもう一度書きなさい」と言っています。これはどのように役立ちますか?もちろん、それはOPの仮説的解決法にも当てはまります。全体が基本的に無意味です... –

+4

@LightnessRacesinOrbit:あなたのコメントは次のように述べています。これは答えではありません。逆に、尋ねられたことを正確に実行します。ゴールの非実用性についてのコメントは、各回答ではなく質問*にする必要があります。 –

+1

おそらく ' – Niall

5

commentsのように、変数の値とその名前の両方の関数に渡す必要があります。これは、マクロの助けを借りて行われなければならない:

#include <iostream> 

template<class T> 
void foo(T var, const char* varname) 
{ 
    std::cout << varname << "=" << var << std::endl; 
} 

#define FOO(var) foo(var, #var) 

int main() 
{ 
    int i = 123; 
    double d = 45.67; 
    std::string s = "qwerty"; 

    FOO(i); 
    FOO(d); 
    FOO(s); 
    return 0; 
} 

出力:

i=123 
d=45.67 
s=qwerty 
+1

'T& 'ない'T' – Yakk

+1

' T& 'は' FOO'が左辺値でのみ機能するという興味深いプロパティを持っています。これはおそらくここで欲しいものです。それ以外の場合は、 'FOO(2 + 2)'を実行することができます。これは、われわれが望むものではないかもしれません。 – KABoissonneault

5

他の人が指摘したように、あなたが実際に変数名を「文字列化」するためにマクロを使用することができます。

あなたが見ることができるように
#define NAMEOF(variable) ((decltype(&variable))nullptr, #variable) 

が、それはカンマ演算子を使用しています。しかし、単に#define NAMEOF(variable) #variableとしてそれを定義する代わりに、次の定義を使用することができます。この式の左の部分は、nullptrからvariableの型へのポインタに(無意味な)変換を行います。その結果はすぐに破棄されます。右の部分は、文字列化された変数の名前を返します。

なぜマクロ内で単に#variableを使用するよりも優れていますか?あなたには、いくつかの種類の変数ではなく、いくつかの任意の文字列またはマクロNAMEOFにリテラルを渡す場合decltype()オペレータに

おかげで、全体のことしかコンパイルします。あなたがその名前を使用します。ここで、コンパイラはあなたに叫ぶますので、あなたがvalue変数の名前を変更リファクタリング将来の間に、あなたは、また、場所を変更することを忘れないであろう場合は、このため

double value = 523231231312.0095; 

cout<< NAMEOF(value) << endl; // value 

cout<< NAMEOF(value1) << endl; // Compiler error: 'value1' was not declared in this scope 

cout<< NAMEOF(42) << endl;  // Compiler error: lvalue required as unary '&' operand 

次の例を考えてみましょうまた、この変数のすべての使用方法をNAMEOFに修正するまで。コメントで

MinGWの-W64(GCC V5.2.0)でテスト


@iammilind@NiallはCに依存しないこのマクロを定義する2つの他の方法を示唆している++ 11固有decltype()演算子:

#define NAMEOF(variable) ((void*)&variable, #variable) 

...か...

// Unlike other definitions, this one, suggested by @Niall, 
// won't get broken even if unary & operator for variable's type 
// gets overloaded in an incompatible manner. 
#define NAMEOF(variable) ((void)variable, #variable) 

// On the other hand, it accepts literals as parameters for NAMEOF, 
// though this might be desired behaviour, depending on your requirements. 
NAMEOF(42); // 42 

ご意見をもとに、@Leonさんの提案で、このようなマクロを使用して、我々が得る:

template<class T> 
void foo(T var, const char* varname) 
{ 
    std::cout << varname << "=" << var << std::endl; 
} 

#define FOO(var) foo(var, NAMEOF(var)) 

int someVariable = 5; 

FOO(someVariable);   // someVariable = 5 

FOO(nonExistingVariable); // compiler error! 
+0

C++ 11が手の届かないところにあれば、単純な '(void *)&v'で十分です。とにかく、良い観察。 – iammilind

+0

アドレス演算子がオーバーロードされている場合は、 '(void)v'で十分/より良いでしょう。 – Niall

+0

@Niallこれは、リテラルを渡す場合を破ります。 'NAMEOF(42)'はもはやコンパイラエラーにつながることはありません。 – TerraPass