我正在编写模板以提取具有特定签名的成员函数的返回类型。我需要这个来创建一个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
版本,但我也希望能够传递函数的名称及其参数签名。
是否有可能做到这样的事情(如果它没有宏,可以获得奖励),还是我坚持为我要检查的每个签名创建一对函数?
答案 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)>{});
}