这个问题已经在这里有一个答案:
我有一个模板函数
template <typename F, typename T> auto foo(F f) { ... }
在这个函数中,我要排序,调用F
:我想打电话给F.template operator()<T>()
,不带参数的 - 但只有当它的存在。否则,我就要回型my_type_t
的一些价值。
我读过这个问题:
Check if a class has a member function of a given signature
和更新:
Using `void_t` to check if a class has a method with a specific signature
和他们的答案。然而,他们似乎都认为你预先知道签名,因此你可以使用std::is_same
以确保该方法确实存在,并产生相关的类型。
在我的情况 - 我不知道是什么类型的检查它反对。
所以,我能做些什么,不作任何这种假设的?
作为评论者建议(感谢@DanHulme),这是可行的与SFINAE没有任何假设 - 它在做的方式类似
Find out whether a C++ object is callable
至少,在一定的假设。
然而,这是需要一点技巧,以获得正确的代码为模板operator()
,因为C ++的语法歧义。我也有些意见加入到简单介绍一下如何SFINAE在这里工作,有利于少-C ++的 - 精明的读者(的代码没有这个问题)。
总之,这里的适应:
#include <type_traits>
namespace detail {
template <class>
struct sfinae_true : std::true_type{};
template <class F, typename T>
static auto test_invoke_operator(int ) ->
sfinae_true<decltype(std::declval<F>().template operator()<T>())>;
template <class, typename>
static auto test_invoke_operator(long) -> std::false_type;
} // namespace detail
template <class F, typename T>
struct has_invoke_operator : decltype( detail::test_invoke_operator<F,T>(int{}) )
{ };
// The overload resolution here will depend on the test for invoke_operator:
// * If F has an operator()<T>, the `int` variant substitution succeeds,
// so has_invoke_operator inherits true_type.
// * If F does not have an operator()<T>, the `int` variant substitution fails,
// but we still get a matching candidate - the `long` variant, which
// means has_invoke_operator inherits false_type
在Coliru例子 - 我们需要用= delete
该类没有任何其他专门的定义,也没有一个通用的定义来表示。