8

次のおもちゃのコード スニペットをコンパイルできないことに関して、Microsoft Connect でこのバグを報告しました。

template <typename... P> struct S {
    template <void(*F)(P...)> static void T() { }
};

void A(int, float) { }
int main() { S<int, float>::T<&A>(); }

エラーは次のとおりです。

test.cpp(2): error C3520: 'P' : parameter pack must be expanded in this context

基本的に、テンプレート パラメーターとして使用する場合、関数シグネチャ内で可変長型を展開することはできません。このコードは (私が思うに) 合法です。少なくとも、GCC 4.7、Clang 3.0、および ICC 13 はすべてサポートしています。

このSOの質問を見たことがありますが、回避策は要求または提供されていません。これが私が探しているものです。

それほど重要ではありませんが (明らかに、私は可変個引数テンプレートを何年も使用せずに過ごしてきました)、このパターンは、私がやりたい作業や C++ で書きたい記事にとって特に重要です。シリアライゼーション、スクリプト バインドなどの 11 のリフレクション手法。これは、Visual Studio ユーザーに役立つものにしたいと考えています (これは、私の業界で圧倒的に支配的なコンパイラ ツールセットであるため)。Microsoft のエンジニアが 2013 RTM までにこれを修正できることを願っていますが、息を止めていません。

これがどのように使用されているかのおもちゃ(今回は記憶から)のサンプルは次のようなものです(少し使いやすくするマクロを差し引いたもの):

Reflect<MyType>("MyType")
.bind("GetMatrix", mat44, &MyType::GetMatrix>()
.bind("Display", void, &MyType::Display>();

もちろん、これはすべて可変個引数テンプレートなしで実行できます。もちろん、大量のコードが必要であり、バインドされたメンバー関数の最大アリティに対する制限を受け入れるだけです。そして、はい、関数をテンプレート パラメーターとして渡すことは重要です。これは、Visual Studio でメンバー関数ポインターがどのように機能するか (可変サイズ) の性質と、Impossively Fast C++ Delegates (私のニッチである) と同等の効率を達成したいという願望のためです。 C++ コミュニティでは、このレベルの最適化が実際に問題になる場合があります) std::function

この VS バグの回避策はありますか? または、VC ++ 12で(コンパイル時)関数ポインターパラメーターを使用するために可変個引数テンプレートを使用する他の方法はありますか?

4

1 に答える 1

6

理由はわかりませんが、typedef で単純化するとうまくいくようです:

template <typename... P>
struct S
{
    typedef void (*MyFunc)(P...);

    template <MyFunc myFunc>
    static void foo() {}
};

void foo2(int, float) {}

int main()
{
    S<int, float>::foo<&foo2>();
}

少なくとも Visual Studio 2013 Ultimate Preview では。

于 2013-07-01T08:48:57.180 に答える