You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17中如何定义检测自定义仿函数的类型特性is_functor?

Implementing is_functor Type Trait in C++17

Alright, let's break down how to build the is_functor type trait you need. First, let's recap the requirements clearly:

  • A "functor" here is a class or union (can be marked final)
  • It must have at least one publicly overloaded operator() (this includes template operators, const/volatile-qualified operators, etc.)

Step 1: Include Required Headers

First, we'll need standard library headers for type traits and value manipulation:

#include <type_traits>
#include <utility> // For std::declval

Step 2: Helper Trait to Detect operator()

We need a way to check if a type has a public operator(), covering both non-template and template versions of the operator. We'll use SFINAE (Substitution Failure Is Not An Error) to handle this:

namespace detail {
    // Helper trait to detect any public operator()
    template <typename T>
    struct has_call_operator {
    private:
        // First check: detect non-template operator() by taking its address
        template <typename U>
        static constexpr auto check(int) -> decltype(&U::operator(), bool{}) {
            return true;
        }

        // Second check: detect if we can call the operator with an int argument (covers template operators)
        template <typename U>
        static constexpr auto check(long) -> decltype(std::declval<U>()(std::declval<int>()), bool{}) {
            return true;
        }

        // Third check: detect if we can call the operator with no arguments
        template <typename U>
        static constexpr auto check(char) -> decltype(std::declval<U>()(), bool{}) {
            return true;
        }

        // Fallback: no operator() found
        template <typename U>
        static constexpr bool check(...) {
            return false;
        }

    public:
        static constexpr bool value = check<T>(0); // Prioritize checks from most to least specific
    };
}

This helper works by trying increasingly general checks:

  1. First, it tries to get the address of a non-template operator() (most specific case)
  2. If that fails, it tries calling the operator with an int (covers template operators that accept integers, which is a common case)
  3. If that fails, it tries a no-argument call
  4. If all checks fail, it returns false

Step 3: Implement the is_functor Trait

Now we combine the class/union check with our has_call_operator helper:

template <class T>
struct is_functor {
    static constexpr bool value = 
        (std::is_class_v<T> || std::is_union_v<T>) && 
        detail::has_call_operator<T>::value;
};

template <class T>
inline constexpr bool is_functor_v = is_functor<T>::value;

Step 4: Test Cases

Let's verify this trait with some common scenarios:

// Valid functors
struct SimpleFunctor { void operator()() {} };
final struct FinalFunctor { void operator()(int) const noexcept {} };
union UnionFunctor { void operator()(double) {} };
struct TemplateFunctor { template <typename U> void operator()(U) {} };
auto lambda = []() {}; // Lambda closure is a class with public operator()

// Invalid cases
struct PrivateOp { private: void operator()() {} };
using FuncPtr = void(*)();
int basic_type = 42;

static_assert(is_functor_v<SimpleFunctor>);
static_assert(is_functor_v<FinalFunctor>);
static_assert(is_functor_v<UnionFunctor>);
static_assert(is_functor_v<TemplateFunctor>);
static_assert(is_functor_v<decltype(lambda)>);

static_assert(!is_functor_v<PrivateOp>);
static_assert(!is_functor_v<FuncPtr>);
static_assert(!is_functor_v<decltype(basic_type)>);

All these assertions should pass in a C++17-compliant compiler.

Key Notes

  • The trait correctly ignores non-class/non-union types (like function pointers or basic types)
  • It handles final classes and unions properly
  • Template operator() are detected via the call-based checks
  • Private operator() are rejected (since the SFINAE checks can't access them)

内容的提问来源于stack exchange,提问作者Vincent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:21:39