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 个重载的辅助函数,一个std::true_type基于兼容性测试,另一个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 回答