6

コンパイルされない次のコードがあります。これは、引数を取るテンプレートクラスの2つの関数です

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() {
    // ...
}

typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() {
    // ....
}

Retのタイプに応じて、メンバーメソッドに特化したいと思います。

誰かアイデアはありますか?

4

2 に答える 2

7

SFINAEは、非テンプレート関数(メンバーまたは非メンバー)では機能しません。

Kerrek SBが指摘しているように、それらを非メンバー関数テンプレートにすることは機能します。または、Xeoが指摘しているように、デフォルトのテンプレート引数を使用してメンバー関数テンプレートにすることもできます。

ただし、これは2つのstd::enable_if条件が重複していないためにのみ機能します。(たとえば)に別のオーバーロードを追加したい場合intは、スケーリングがうまくいかないことがわかります。何をしたいかにもよりますが、タグディスパッチは通常、ディスパッチしたい複数の選択肢があるSFINAEよりも拡張性が高くなります。

#include<type_traits>

template<typename Ret>
class Foo
{
public:
    void _on_dispatched()
    {
        // tag dispachting: create dummy of either std::false_type or std::true_type
        // almost guaranteed to be optimized away by a decent compiler
        helper_on_dispatched(std::is_void<Ret>()); 
    } 

private:
    void helper_on_dispatched(std::false_type)
    {
        // do stuff for non-void
    }

    void helper_on_dispatched(std::true_type)
    {
        // do stuff for void
    }
};

int main()
{
    Foo<void>()._on_dispatched();
    Foo<int>()._on_dispatched();
    return 0;
}
于 2012-08-17T08:43:55.930 に答える
3

SFINAEはテンプレートでのみ機能します。コードを少し変更するだけでコンパイルできます。

template <typename Ret>
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ }

template <typename Ret>
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ }

使用法:

auto q = _on_dispatched<int>();

もちろん、関数の戻り型は推論できないため、推測することはできません。ただし、このテンプレートを別のテンプレート内にパックすることができます。

template <typename T>
struct Foo
{
    // insert templates here, maybe privately so

    T bar() { return _on_dispatched<T>(); }
};
于 2012-08-17T09:08:38.003 に答える