我想设计一个课程:
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宏(希望没有))?
实现@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
}