默认参数,如果默认可构造

时间:2016-05-19 17:39:22

标签: c++ templates c++11 sfinae

我遇到一个小问题,我的代码有效,但不理想。

我有一个以谓词作为参数的函数。我想支持这些语法:

myClass.foo([](auto param){ return true; }); // predicate sent as parameter
myClass.foo<PredicateType>(); // predicate type sent as template argument
myClass.foo(); // default predicate took

然而,为了做到这一点,我复制了这样的功能:

struct MyClass {
    template<typename Predicate = DefaultPredicate&&, std::enable_if_t<std::is_default_constructible<detail::decay_t<Predicate>>::value, int> = 0>
    void foo(Predicate&& p = std::decay_t<Predicate>{}) {
        // stuff...
    }

    template<typename Predicate, std::enable_if_t<!std::is_default_constructible<detail::decay_t<Predicate>>::value, int> = 0>
    void foo(Predicate&& p) {
        // exact same stuff...
    }
};

有没有办法在不重复我的代码的情况下执行此操作? 理想的是拥有一个功能。我怎么能这样做,最好是在c ++ 11?

2 个答案:

答案 0 :(得分:5)

剥去无意义的SFINAE和同样毫无意义的decay

struct MyClass {
    template<typename Predicate = DefaultPredicate>
    void foo(Predicate&& p = Predicate{}) {
        // stuff...
    }    
};

默认函数参数是单独实例化的,并且只有在实际需要它们时才会实例化。

答案 1 :(得分:4)

只需创建一个不带参数的模板函数,然后转到带谓词的函数:

#include <iostream>

struct Predicate {};
struct DefaultPredicate {};
struct MyClass {
    template<typename Predicate>
    void foo(Predicate&& p) {
        std::cout << "Stuff\n";
    }

    template<typename Predicate = DefaultPredicate>
    void foo() {
        std::cout << "Forward ";
        foo(Predicate{});
    }
};

int main() {
    MyClass my;
    my.foo<>(); // DefaultPredicate
    my.foo<DefaultPredicate>();
    my.foo<Predicate>();
    my.foo(Predicate());
    return 0;
}