web-dev-qa-db-ja.com

C ++で関数名にエイリアスを割り当てるにはどうすればよいですか?

型、変数、または名前空間の新しい名前を簡単に作成できます。しかし、関数に新しい名前を割り当てるにはどうすればよいですか?たとえば、hollerにはprintfという名前を使用します。 #defineは明らかです...他の方法はありますか?

解決策:

  1. _#define holler printf_
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }
91
Agnel Kurian

さまざまなアプローチがあります。

  • 非テンプレートの非オーバーロード関数を使用するC++ 11では、次を使用できます。

    const auto& new_fn_name = old_fn_name;
    
  • この関数に複数のオーバーロードがある場合は、static_castを使用する必要があります。

    const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
    

    例:関数std::stoiには2つのオーバーロードがあります

    int stoi (const string&, size_t*, int);
    int stoi (const wstring&, size_t*, int);
    

    最初のバージョンのエイリアスを作成する場合は、次を使用する必要があります。

    const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
    

    注:オーバーロードされたすべてのバージョンが機能するように、オーバーロードされた関数のエイリアスを作成する方法がないため、常に正確な関数のオーバーロードを指定する必要があります。

  • C++ 14では、constexprテンプレート変数をさらに使用できます。これにより、テンプレート化された関数のエイリアスを作成できます。

    template<typename T>
    constexpr void old_function(/* args */);
    
    template<typename T>
    constexpr auto alias_to_old = old_function<T>;
    
  • さらに、C++ 11以降では、std::mem_fnという関数があり、メンバー関数のエイリアスを作成できます。次の例を参照してください。

    struct A {
       void f(int i) {
          std::cout << "Argument: " << i << '\n';
       }
    };
    
    
    A a;
    
    auto greet = std::mem_fn(&A::f); // alias to member function
    // prints "Argument: 5"
    greet(a, 5); // you should provide an object each time you use this alias
    
    // if you want to bind an object permanently use `std::bind`
    greet_a = std::bind(greet, a, std::placeholders::_1);
    greet_a(3); // equivalent to greet(a, 3) => a.f(3);
    
102
sasha.sochka

関数ポインターまたは関数参照を作成できます。

void fn()
{
}

//...

void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
34
Brian R. Bondy
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;

元気ですか?.

21
jer

int (*holler)(const char*, ...) = std::printf;

10
MSalters

インラインラッパーを使用します。両方のAPIを取得しますが、単一の実装を維持します。

7
John

fluentcpp から:ALIAS_TEMPLATE_FUNCTION(f、g)

#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
template<typename... Args> \
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \
{ \
    return lowLevelF(std::forward<Args>(args)...); \
}
2
sailfish009

ここでIMOに言及する価値があります。元の質問(および素晴らしい回答)は、関数の名前を変更する場合(間違いなく適切な理由があります!)名前を保持します。これにはusingキーワードがあります。

namespace deep {
  namespace naming {
    namespace convention {
      void myFunction(int a, char b) {}
    }
  }
}
int main(void){
  // A pain to write it all out every time
  deep::naming::convention::myFunction(5, 'c');

  // Using keyword can be done this way
  using deep::naming::convention::myFunction;
  myFunction(5, 'c');  // Same as above
}

これには、スコープに限定されるという利点もありますが、常にファイルのトップレベルで使用できます。私はこれをcoutendlによく使用するので、ファイルの先頭にあるstdのすべてを古典的なusing namespace std;で取り込む必要はありませんが、 std::this_thread::sleep_for()のようなものを1つのファイルまたは関数でたくさん使用しますが、どこでも、名前空間の他の関数でも使用しません。いつものように、.hファイルで使用することはお勧めしません。さもないと、グローバル名前空間を汚染することになります。

これは上記の「名前変更」と同じではありませんが、多くの場合、本当に必要なものです。

0
Kevin Anderson