使用经典的重载决策规则创建依赖于std :: invoke的重载集类

问题描述 投票:0回答:1

我想设计一个课程:

template <class... F> class overload_set;

这将采用构造中的callables列表,并将有一个operator()将应用经典的重载决策规则来决定调用哪个函数。

对于两个函数,这将是这样的:

template <class F0, class F1>
struct overload_set: F0, F1
{
    constexpr overload_set(F0 f0, F1 f1): F0(f0), F1(f1) {}
    using F0::operator();
    using F1::operator();
};

但是,这只适用于函数对象,而我希望它可以与任何使用std::invoke(自由函数,函子,lambda,函数成员,成员......)的可调用函数一起使用。当然,我希望能够使用函数成员的ref / const资格的所有子集,例如:

struct subtle
{
    constexpr void operator()() noexcept {}
    constexpr void operator()() & noexcept {}
    constexpr void operator()() && noexcept {}
    constexpr void operator()() const& noexcept {}
    constexpr void operator()() const&& noexcept {}
};

如果subtle传递给overload_set它应该运作良好。

是否有可能在C ++ 17中创建这样的类overload_set,如果是这样的话(使用尽可能多的模板元编程技巧,但尽可能少的C宏(希望没有))?

c++ overloading c++17 template-meta-programming perfect-forwarding
1个回答
1
投票

实现@KerrekSB所说的内容

template<typename F>
struct functor
{
    using type = F;
};

template<bool Noexcept, typename R, typename... Args>
struct functor<R (*)(Args...) noexcept(Noexcept)>
{
    struct fn
    {
        R (*p)(Args...) noexcept(Noexcept);
        R operator()(Args&&... args) const noexcept(Noexcept)
        {
            return p(std::forward<Args>(args)...);   
        }
    };
    using type = fn;
};

template<typename F>
using func = typename functor<std::decay_t<F>>::type;

template<typename... Fs>
struct over : func<Fs>...
{
    template<typename... Gs>
    over(Gs&&... gs) : func<Fs>{std::forward<Gs>(gs)}... {}

    using func<Fs>::operator()...;
};

template<typename... Gs>
auto makeover(Gs&&... gs)
{
    return over<func<Gs>...>{std::forward<Gs>(gs)...};   
}

你用它作为

int main()
{
    auto o = makeover([](int){ std::cout << "int\n"; }, 
                     +[](double){ std::cout << "double\n"; });
    o(42);    // prints int
    o(42.0);  // prints double

    auto o2 = makeover(+[]() noexcept {});
    std::cout << noexcept(o2());  // prints 1
}

Demo

© www.soinside.com 2019 - 2024. All rights reserved.