2

次のような関数を作成したい:

template < typename Other, typename Func, typename T, typename ...Rest >
void  visit( Other &&other, Func &&visitor )
{
    // Wrap "visitor" and "other" with "std::forward" calls
    visitor( make_object<T>(other) );
    visit<Other, Func, Rest...>( other, visitor );
}

問題は、「Func」がリスト内のすべてのタイプをサポートしていない可能性があることです。その場合、コンパイラは最初の悪いタイプで失敗します。私はそれを望んでいません。代わりに、デフォルトのアクションを実行したいです(私の場合は、何もしません)。

template < typename Other, typename Func, typename T, typename ...Rest >
void  visit( Other &&other, Func &&visitor )
{
    // Wrap "visitor" and "other" with "std::forward" calls
    if ( Func-can-support-T-either-directly-or-by-converting-it )
        visitor( make_object<T>(other) );
    else
        ;  // might be a throw or a logging instead
    visit<Other, Func, Rest...>( other, visitor );
}

2 つのオーバーロードされた補助関数を作成できると思います。1 つstd::true_typeは互換性テストに基づいており、もう 1 つはstd::false_type. しかし、どうすればテストを作成できますか?

(より良いタイトルや追加のタグの提案を歓迎します。)

4

1 に答える 1

3

コンピューティングのすべての問題と同様に、必要なのは単純なレベルの間接化だけです:)

applyこれは、物事が思い通りに機能しない場合のデフォルトの実装を持つ単純な関数です。

template <typename Func>
void apply(Func&& f, ...) { std::cout << "default\n"; }

template <typename Func, typename T>
auto apply(Func&& f, T&& t) -> decltype(f(std::forward<T>(t))) {
    return f(std::forward<T>(t));
}

簡単に実行できます。

struct Foo {};
struct Bar {};

struct F {
    void operator()(Foo) { std::cout << "Foo\n"; }
    void operator()(Bar) { std::cout << "Bar\n"; }
};

int main() {
    F f;
    Foo foo;
    Bar bar;
    int i;
    apply(f, foo);
    apply(f, bar);
    apply(f, i);
}

Ideone は次の出力を提供します。

Foo
Bar
default

予想通り。

于 2012-04-21T10:09:25.303 に答える