传递具有未知签名的成员模板函数,并可能重载到模板

时间:2015-06-27 14:41:08

标签: templates c++11 signature member-function-pointers

我正在编写模板以提取具有特定签名的成员函数的返回类型。我需要这个来创建一个type_trait来验证这种类型的一些约束,这样我可以/regserver如果我可以使用它们进行某些优化。目前我有这个代码,似乎工作正常:

enable_if

虽然我可以通过更改传递给#include <iostream> #include <type_traits> struct A { const double & foo(size_t i) const; const int & foo(size_t i); }; struct B { const double & foo(size_t i); size_t bar() const; }; struct C { }; template <typename T> struct remove_cv_ref { using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type; }; template <typename Z> auto fooRetType(Z* z) -> // Here I select the function name and its arguments typename remove_cv_ref<decltype(z->foo(std::declval<size_t>()))>::type; // Fallback, returns whatever type template <typename Z> auto fooRetType(...) -> int; template <typename M> // Here I can select between const and non-const versions // (currently const) using K = decltype(fooRetType<const M>(0)); int main() { // Here only A has a foo(size_t) const, so it's the only // one that matches. std::cout << "Is double? " << std::is_same<double, K<A>>::value << "\n"; std::cout << "Is double? " << std::is_same<double, K<B>>::value << "\n"; std::cout << "Is double? " << std::is_same<double, K<C>>::value << "\n"; return 0; } 的类型轻松选择方法的const和非const版本,但我也希望能够传递函数的名称及其参数签名。

是否有可能做到这样的事情(如果它没有宏,可以获得奖励),还是我坚持为我要检查的每个签名创建一对函数?

1 个答案:

答案 0 :(得分:1)

namespace detail{
    template<typename T>
    using identity = T;

    template<typename...>
    struct voider { using type = void; };
    template<typename... Ts> using void_t = typename voider<Ts...>::type;

    template<typename Sig, template<typename> class M = identity, typename = void>
    struct has_foo : std::false_type {};

    template<typename C, template<typename> class M, typename... Args>
    struct has_foo<C(Args...), M, void_t<decltype(std::declval<M<C>&>().foo(std::declval<Args>()...))>> : std::true_type {};
}

template<typename Sig>
using has_foo = detail::has_foo<Sig>;

template<typename Sig>
using has_const_foo = detail::has_foo<Sig, std::add_const_t>;

int main() {
    static_assert(has_const_foo<A(size_t)>{});
    static_assert(has_foo<B(size_t)>{});
    static_assert(!has_foo<C(size_t)>{});
}