2016-08-02 4 views
1

マクロに渡された名前をmangleして、関数の名前として使用したい。 C++の関数として使用するマクロパラメータ名を変換する

#define foo(name) void name(const string& in) { \\do something } 

しかし、私はので、私は機能としてそれを使用するために適切なものに名前を変更する必要があり、このマクロは、この foo(Bar::do)のようなパラメータを指定して呼び出す必要があるとします。たとえば、私は以下のように fooをマクロを呼んでいます。

これを実装する方法はありますか?私はC++ 11とg ++ 5.xを使用します。

編集:

は私が遭遇した問題は、それが制限なく使用することができること、なぜならマクロの古いバージョンを有するのであるので、今、私はマクロを使用しています私のコードの多くの部分を持っていますfoo(Bar::do)のようなものですが、これらの名前を使用して関数を生成する必要がありますが、関数名は区別しなければならないので、マクロ入力パラメータを関数名として使用することにしました。

これは一例です:

void Bar::do(some_parameters) 
{ 
    FOO(Bar::do); 
} 

これは、今、私はこのように、この部分の上に2番目のマクロを追加したい、私が前に持っていたコードの一部です:

FOO2(Bar::do) 
void Bar::do(some_parameters) 
{ 
    FOO(Bar::do); 
} 

両方の名前は同じでなければなりませんが、FOO2は入力パラメータに基づいて関数を生成する必要があります。

EDIT2:

私は、問題をより正確に説明するためにここにしてみてください。

#define FOO(name) \ 
    some codes here 

しかし、今、私は以下のように拡大することができ、マクロを持っているとします:

私はこのようなものを使用することができます
#define FOO2(name) void proper_fcn_name(name)(const string &name){ do the same thing here} 
#define FOO(name) proper_fcn_name(name)(#name) 

私はこのようなマクロを持っていた、前に
FOO2(some_name) 
void Bar::fcn() 
{ 
    FOO(some_name); 
} 

some_nameの形式がBar::fcnの場合、proper_fcn_nameは、たとえばBar_fcnに変更します。 some_nameBar::fcnた場合、最終的に私は、このような何かを持っていることを望む:

void Bar_fcn(const stirng& name) { } 
void Bar::fcn() 
{ 
    Bar_fcn("Bar::fcn"); 
} 

私はBar::fcnは名前だけですが、私の図書館利用者が前にこのスタイルを使用するので、私はこれを考慮する必要があることに言及しなければなりません。

+0

マクロが実際にやりたいことを理解していない/それが今ではないということを私は理解していません。 – chris

+0

私は 'bar :: do'や' bar do'を 'bar_do'などに変更して、機能として使用できるものを変更したいと思います。それは名前のmangilngのようなものです。 – MohsenTamiz

+1

なぜ 'std :: function'の代わりにマクロを使用していますか? – Tas

答えて

1

私はあなたの質問による興味があったし、次の例作られた:最初のテストは

第二の試験(それが出力されます)、それは動作します実際に

#include <iostream> 
#include <string> 
using namespace std; 
#define foo(name) void name (const string& in) { cout << in << endl; } 

// function with name bar_do 
foo(bar_do) 

// function with name bar_do 
foo(do_bar) 

int main(void) 
{ 
    bar_do("The first test"); 
    do_bar("The second test"); 
} 

を、

しかし、私はあなたがそれから何を望んでいるのか理解できませんマクロ定義の奇妙な使い方 - 異なる名前の同一の関数を生成するための自動コピーペーストアプローチのように見える。

UPDATE

あなたは本当に名前空間(例えばBar)を使用したい場合は、次の例を検討:あなたが理解する必要があり

#include <iostream> 
#include <string> 
using namespace std; 
#define foo(name) void name (const string& in) { cout << in << endl; } 

namespace Bar{ 
    void func(const string& in); 
} 

foo(Bar::func) 

int main(void) 
{ 
    Bar::func("The special test"); 
} 

を、その名前空間を定義する必要があり、かつdoはのキーワードですC++言語(関数名として使用しないでください)

UPDATE 2

それはあなたの古いコードにFOO(Bar,do);FOO(Bar::do);を変更することが可能である場合は、通話のためにと定義についてBar_do識別子を生成するために、単純な置換を行うことができます。

#include <iostream> 
#include <string> 
using namespace std; 

#define defgen(class_name,method_name) void class_name##_##method_name(const string& in) { cout << in << endl; } 
#define callgen(class_name,method_name,...) class_name##_##method_name(__VA_ARGS__); 

// produses definition 
defgen(Bar,do) 

int main(void) 
{ 
    // produces call with particular value as an argument 
    callgen(Bar,do,"The call test"); 
} 

kfsone(あなたの質問にコメントで)言いました:

MYMACRO(:: B)A_b_stub

が、unfortが生じる可能性があります他の文字との置換えをどうすればいいのかわかりません(とは考えられません)。::_)。

+0

@VolAd投稿した編集メモを考慮してください。 – MohsenTamiz

+0

編集メモにスニペットコードを追加しました。これにより、問題がより明確になる場合があります。 'Bar :: do'は私にとって意味がなく、他のいくつかの開発者が目的のためにそれを使用しています。私は' Bar'が名前空間やクラスであるとは確信していません。このマクロからの開発者要求を関数名として使用できる名前に変換します。 – MohsenTamiz

+0

"バーが名前空間またはクラスであるかどうかはわかりません"これはマクロを優先する引数ではありません。これは、適切な命名規則を作成して使用するように努力する必要があることを意味します。例えば私は 'this_thing'を名前空間に使い、' ThisThing'をクラスに使います。実際には、これはマクロの別の議論です。あなたのマクロのコードを読んでいる人々(あなたの将来の自己を含む)は、 '' foo'が何であるか、 'bar_do'が宣言/定義されているのか分かりません。ちょうど母国語の機能を使用してください。マクロは、あなたが説得力のある理由がある場合にのみ使用してください。これは実際にはそうではありません。 –

2

私はそれはあなたがこれを行うべきではないと十分に強調することができるとは思わない、これはここにXYの問題があるように聞こえる。

おそらく、とにかく十分な説教は、ここで回避策です

など、なぜあなたはそれがどのように使われるか、この関数を生成しようとしている、完全な形で問題を説明する必要があります

#include <iostream> 
#include <map> 
#include <string> 
#include <functional> 

std::map<std::string, std::function<void(const std::string&)>> g_functions; 

#define FOO(name) static void* nonsense##__COUNTER__ =    \ 
        (void*)&( g_functions[ #name ] =     \ 
        [](const std::string& in)       \ 
        {             \ 
        std::cout << "generated function for : " << #name \ 
           << " called with arg:" << in << std::endl; \ 
        }); 
#define FOO2(name) {g_functions[ #name ](#name); } 

namespace Bar 
{ 
    FOO(Bar::func) 
    void func() 
    { 
     FOO2(Bar::func); 
    } 

} 

int main() { 
    Bar::func(); 
    return 0; 
} 

は、コンパイラに__COUNTER__がない場合は、ほとんどの場合__LINE__を使用することができます(このファイルの上に1つ以上の醜いハックがあります)。

+0

私の投稿のEdit2メモを見てください。私は問題をより明確に説明しようとしましたが、あなたの提案は問題解決のための私の要求を満たしていないと思います/ – MohsenTamiz

+0

@MohsenTamizよく私はあなたが望むように機能を生成します。ラムダを使用することによって、コンパイラに名前を生成させます。私のソリューションには、マップルックアップとマイナーなstd ::関数呼び出しの非効率性に関する明らかなオーバーヘッドがあります。しかし、そうでなければ、私はあなたの要求をどのように満たしていないのか分かりません。 – PeterT

+0

はい、私はそれを得ましたが、ラムダ関数内の '#name 'は' in'に変更する必要があります。あなたのソリューションは問題を解決することができますが、このソリューションには明らかなオーバーヘッドがあります。私はこれを考慮する必要があると思います。他に解決策がなければ、今できることはあなたのものかもしれません。しかし、最初に、オーバーヘッドの少ない他の可能なソリューションを探していなければなりません。 – MohsenTamiz

関連する問題