2017-01-20 7 views
6

関数に "using"を使用する方法は?関数に "using"を使用する方法は?

void (*Bf)(int) = f; 

か、単に機能でラップ:fは単なる機能である場合の例

class A; 
void f(int); 

struct B 
{ 
    using BA = A; 
    using Bf = f; ??? 
}; 
+0

http://en.cppreference.com/w/cpp/language/using_declaration –

答えて

11

あなたはいらいらすることができ、型を指定する心配する必要はありませんその方法

struct B 
{ 
    using BA = A; 
    constexpr static auto Bf = f; 
} 

を行うことができます。

静的ではない変数を宣言したくない場合は、オブジェクトのすべてのコピーが関数ポインタを持ち歩くことになります。あなたはまたそれを変更することはできません。なぜなら、あなたはそれを再割り当てすることができるからです。コンパイラは、Bfへの呼び出しが実際にはfを呼び出しているか、または関数間接費を支払っていることを特定のコンテキストで証明する必要があるため、実行時に潜在的に決定されることは望ましくありません。 constexprは、この最後の2つのポイントを処理します。

+0

TBH任意の適切なオプティマイザは、単純な関数ポインタが定数式によって一度初期化され、後で書き込まれないという助けなしに見つけることができます。あなたはSSAをやっているときにそれをほとんど無料で手に入れることができます。 – MSalters

+0

@MSalters私はこのような言葉を常に見ており、ほとんど常に間違っています。バランス上、コンパイラが関数ポインタをインライン化することは非常にまれです。 https://godbolt.org/g/mBMZeF。静的変数は基本的にはグローバル変数であり、変更可能な場合はいつでもどこでも変更できます。だから、単純なプログラムでは実現不可能な、プログラム全体の解析をせずにインライン化するのは、合法ではありません。インスタンス変数を使用すると、メンバ関数ポインタを呼び出す関数がインスタンスが構築されている場所までインライン展開されている場合に動作します。しかし、それは大きいです。 –

+0

グローバル(およびクラススタティックス)の問題は、SSAが事実上不可能であるということです。 SSAは、すべての書き込みの可視性だけでなく、その順序も要求します。そのため、グローバルはオプティマイザにとって単純ではありません。しかし、これはすべてのグローバルのプロパティであり、グローバル関数ポインタに特有のものではありません。 – MSalters

2

ためには、メンバ関数ポインタを追加することができますいずれか

void Bf(int i) { f(i); } 

はおそらく好みます後者は、Bに余分なメンバーを追加することを避けるためです。


fが関数テンプレートである場合は、あなただけのエイリアス、あなたはそれに転送する必要があるだろうことはできません。

template <class... Args> 
auto Bf(Args&&... args) 
    -> decltype(::f(std::forward<Args>(args)...)) 
    noexcept(noexcept(::f(std::forward<Args>(args...)))) 
{ 
    return ::f(std::forward<Args>(args)...); 
} 

うん...です。

+2

どれ理由 'オートBfは= f; 'は可能性はない? – Rakete1111

+1

これは良い解決策ではないと思います。 'B'のすべてのインスタンスは関数ポインタを持ち、そのサイズを膨らませます。また、再割り当てすることもできます。ユーザーは 'using'宣言を開始点として使用するので、すべてのインスタンスで同じで、変更できないことは明らかです。 –

+0

@Raketeそれは不正な形だからです。 – Barry

2

Nir Friedman's answerは素晴らしいですが、fがオーバーロードされている場合には機能しません。 C++ 14では

あなたはa generic lambdaで、このためのソリューションを持つことができます。

struct B { 
    using BA = A; 
    static constexpr auto BF = [](auto&&... args) { 
    return f(std::forward<decltype(args)>(args)...); 
    }; 
}; 

をそれが唯一の理由std::forwardの冗長性のあるビットcomplicatを思われる場合。私が把握する(しかしfがのparamsとして参照型を持つ場合、それは失敗するとしてこれを使用していない)、それを簡単にするためにstd::forwardせずにそれを表示します:

struct B { 
    using BA = A; 
    static constexpr auto BF = [](auto... args) { return f(args...); }; 
}; 
0

差がfながらAがちょうどタイプであるということです実際の関数です。あなたがfタイプとしてBfを定義するためにusingを使用する場合は、使用します。

using Bf = decltype(f); 
+0

これはコメントだと思います。 – HolyBlackCat

関連する問題