我有一个模板函数
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
确保该方法确实存在并产生相关类型。
就我而言-我不知道要针对哪种类型进行检查。
那我该怎么做,这没有做任何假设?
答案 0 :(得分:-1)
正如评论员所建议的(感谢@DanHulme),这在SFINAE上无需任何假设即可完成-类似于
Find out whether a C++ object is callable
至少在一定的假设下。
但是,由于C ++语法的含糊性,对于模板化的operator()
正确获取代码有些棘手。我还添加了一些评论,以简要地解释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
来表明该类 没有任何其他专门的定义,也没有广义的定义。