cda*_*ara 14 c++ metaprogramming variadic-templates c++11 c++14
所以我非常熟悉测试成员函数是否存在的范例.目前此代码有效:
#include <iostream>
#include <type_traits>
struct has_mem_func_foo_impl {
template <typename U, U>
struct chk { };
template <typename Class, typename Arg>
static std::true_type has_foo(chk<void(Class::*)(Arg), &Class::foo>*);
template <typename, typename>
static std::false_type has_foo(...);
};
template <typename Class, typename Arg>
struct has_mem_func_foo : decltype(has_mem_func_foo_impl::template has_foo<Class,Arg>(nullptr)) { };
struct bar {
void foo(int) { }
};
int main() {
static_assert( has_mem_func_foo<bar, int>::value, "bar has foo(int)" );
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我稍作调整:
#include <iostream>
#include <type_traits>
struct has_mem_func_foo_impl {
template <typename U, U>
struct chk { };
template <typename Class, typename... Arg>
static std::true_type has_foo(chk<void(Class::*)(Arg...), &Class::foo>*);
template <typename, typename...>
static std::false_type has_foo(...);
};
template <typename Class, typename... Arg>
struct has_mem_func_foo : decltype(has_mem_func_foo_impl::template has_foo<Class,Arg...>(nullptr)) { };
struct bar {
void foo(int) { }
};
int main() {
static_assert( has_mem_func_foo<bar, int>::value, "bar has foo(int)" );
}
Run Code Online (Sandbox Code Playgroud)
我的静态断言失败了.我的印象是,当扩展到他们的位置时,可变参数模板参数包被视为相同.gcc和clang都会产生失败的静态断言.
因此,我的问题的真正根源是这种标准行为吗?当测试存在可变模板成员函数时,它也会失败.
我看到的问题Arg...是通过int是不够的.编译器在其末尾添加新的args是有效的.
从而无法推断添加到其末尾的内容nullptr_t,因此编译器说"我放弃了,而不是这种情况".
#include <iostream>
#include <type_traits>
template<class Sig>
struct has_mem_func_foo_impl;
template<class R, class...Args>
struct has_mem_func_foo_impl<R(Args...)> {
template <typename U, U>
struct chk { };
template <typename Class>
static constexpr std::true_type has_foo(chk<R(Class::*)(Args...), &Class::foo>*) { return {}; }
template <typename>
static constexpr std::false_type has_foo(...) { return {}; }
};
template <typename Class, typename Sig>
struct has_mem_func_foo :
decltype(has_mem_func_foo_impl<Sig>::template has_foo<Class>(nullptr))
{};
struct bar {
void foo(int) { }
};
int main() {
static_assert( has_mem_func_foo<bar, void(int)>::value, "bar has foo(int)" );
}
Run Code Online (Sandbox Code Playgroud)
我们移动Args...到类本身,然后只将类型传递给函数.这会阻止演绎,这使得nullptr转换为成员函数指针变得可行,并且事情再次起作用.
我还包括一些改进的基于签名的语法,这也意味着它支持返回类型匹配.
请注意,您可能会问错误的问题.您正在询问是否存在具有特定签名的成员函数:通常您要知道的是,是否存在可以使用某组参数调用的成员函数,其返回类型与您的返回值兼容.
namespace details {
template<class T, class Sig, class=void>
struct has_foo:std::false_type{};
template<class T, class R, class... Args>
struct has_foo<T, R(Args...),
typename std::enable_if<
std::is_convertible<
decltype(std::declval<T>().foo(std::declval<Args>()...)),
R
>::value
|| std::is_same<R, void>::value // all return types are compatible with void
// and, due to SFINAE, we can invoke T.foo(Args...) (otherwise previous clause fails)
>::type
>:std::true_type{};
}
template<class T, class Sig>
using has_foo = std::integral_constant<bool, details::has_foo<T, Sig>::value>;
Run Code Online (Sandbox Code Playgroud)
尝试调用T.foo(int),并检查返回值是否兼容.
为了好玩,我做的类型has_foo实际上是true_type或false_type,没有继承,从.我可能只有:
template<class T, class Sig>
using has_foo = details::has_foo<T, Sig>;
Run Code Online (Sandbox Code Playgroud)
如果我不想要那个额外的功能.
| 归档时间: |
|
| 查看次数: |
280 次 |
| 最近记录: |