检查可调用签名参数是否是任何指针类型或可转换为特定类型?

问题描述 投票:0回答:2

我正在使用宏来进行编译时签名匹配,如下所示:

#define ifSigMatch(sig) if constexpr (std::is_same_v<decltype(std::function{std::forward<Foo>(f)}), std::function<sig>>)

template <class T, class Foo> void afoo(Foo f) {
  ifSigMatch(void(T)) { ... }
  ifSigMatch(bool(T)) { ... }
  ifSigMatch(bool(T, int)) { ... }
  ...
}

有没有办法处理

Foo
的第一个输入参数是任何指针类型的情况,或者参数可以隐式转换为
T
,而不需要向
afoo
添加更多模板参数?

最好是 c++17 或更低版本。

c++ templates type-conversion metaprogramming method-signature
2个回答
0
投票

要处理

Foo
的第一个输入参数是任何指针类型或可隐式转换为
T
的情况,您可以将 SFINAE(替换失败不是错误)与
std::enable_if
结合使用。以下是您如何修改宏和模板函数
afoo
以实现此目的,而无需添加更多模板参数:

#include <functional>
#include <type_traits>

#define ifSigMatch(sig) if constexpr (std::is_invocable_v<Foo, sig>)

template <class T, class Foo> 
void afoo(Foo f) {
    ifSigMatch(T*) { ... }
    else ifSigMatch(std::enable_if_t<std::is_convertible_v<std::invoke_result_t<Foo, T>, T>, T>) { ... }
    else ifSigMatch(bool(T)) { ... }
    else ifSigMatch(bool(T, int)) { ... }
    // Add more conditions as needed
    // ...
}


0
投票

您可以使用具有类模板专门化的辅助类来获取返回类型和参数类型,然后在 constexpr 方法中使用它们来比较签名。

如果您想允许返回类型可转换为您指定的类型,可以使用

std::is_convertible_v
代替
std::is_same_v

#include <type_traits>

template <typename>
struct Function; // This primary template is not defined.

template <typename R, typename... Args>
struct Function<R(Args...)> {
    template <typename Foo>
    constexpr bool matchesSig() {
        if constexpr (std::is_invocable_v<Foo, Args...>) {
            // only return true when the return type is EXACTLY as specified
            // otherwise, ifSigMatch(bool(T)) would also always imply
            // ifSigMatch(void(T)) to be true
            return std::is_same_v<std::invoke_result_t<Foo, Args...>, R>;
        }
        return false;
    };
};

#define ifSigMatch(sig) if constexpr (Function<sig>().template matchesSig<Foo>())
© www.soinside.com 2019 - 2024. All rights reserved.