gpt4 book ai didi

c++11 - 仿函数的编译时检查

转载 作者:行者123 更新时间:2023-12-01 05:00:00 24 4
gpt4 key购买 nike

我想在我的代码中进行编译时检查,以确保给定的类重载了 ()运算符,该运算符采用 const char *和一个 size_t作为参数,并且它的返回类型是一个无符号整数。

我已经尝试了从 StackOverflow 中提取的几个代码片段,但我对我编写的解决方案并不满意:

#include <type_traits>
#include <cstdint>
#include <iostream>
#include <memory>

template<class>
struct sfinae_true : std::true_type{};

namespace detail{
template<class T>
static auto test(int)
-> sfinae_true<decltype(std::declval<T>()(static_cast<const char *>(nullptr), static_cast<size_t>(0u)))>;
template<class>
static auto test(long) -> std::false_type;
} // detail::

template<class T>
struct is_functor : decltype(detail::test<T>(0)){ };

template <typename T, typename HashFn,
typename std::enable_if<std::is_unsigned<T>::value, int>::type = 0>
struct Calculation {
Calculation() {
static_assert(is_functor<HashFn>(), "BAD signature");
typedef typename std::result_of<decltype(&HashFn::operator())(HashFn, const char *, size_t)>::type return_type;
static_assert(std::is_unsigned<return_type>::value, "BAD return type");
}

T output() {
return static_cast<T>(HashFn()(nullptr, 10));
}
};

struct Hash {
uint32_t operator ()(const char *buffer, size_t n) const {
return 65;
}
};

int main() {
Calculation<uint64_t, Hash> c;
c.output();
}

很抱歉代码的长度,我尽量让它尽可能小。

这是我不喜欢我的代码的地方:
  • 如果我替换 intsize_t在重载()时的参数列表中运算符,编译时没有错误,因为 size_t可以隐式转换为 int .
  • 如果签名不正确(例如,我在重载运算符时删除了 const),则第一个断言失败。但是因为编译没有停止,所以得到三个错误提示,编译输出有点乱
    rty.cpp: In instantiation of ‘Calculation<T, HashFn, <anonymous> >::Calculation() [with T = long unsigned int; HashFn = Hash; typename std::enable_if<std::is_unsigned<_Tp>::value, int>::type <anonymous> = 0]’:
    rty.cpp:41:31: required from here
    rty.cpp:24:5: error: static assertion failed: BAD signature
    static_assert(is_functor<HashFn>(), "BAD signature");
    ^
    rty.cpp:25:104: error: no type named ‘type’ in ‘class std::result_of<unsigned int (Hash::*(Hash, const char*, long unsigned int))(char*, long unsigned int) const>’
    typedef typename std::result_of<decltype(&HashFn::operator())(HashFn, const char *, size_t)>::type return_type;
    ^
    rty.cpp:26:75: error: no type named ‘type’ in ‘class std::result_of<unsigned int (Hash::*(Hash, const char*, long unsigned int))(char*, long unsigned int) const>’
    static_assert(std::is_unsigned<return_type>::value, "BAD return type");
  • 我想对 static_assert 进行一次调用,例如:
    static_assert(is_correct_functor<HashFn>(), "BAD implementation");

  • 我怎样才能做到这一点?谢谢你的帮助。

    我正在使用 C++11 并使用 g++4.8 进行编译

    最佳答案

    你可以用这个callable_traits获取仿函数的返回类型和参数类型,并使用 std::is_samestatic_assert 中做断言

    // callable_traits

    namespace detail {
    template <class ReturnType, class... Args>
    struct callable_traits_base
    {
    using return_type = ReturnType;
    using argument_type = std::tuple<Args...>;

    template<std::size_t I>
    using arg = typename std::tuple_element<I, argument_type>::type;
    };
    }

    template <class T>
    struct callable_traits : callable_traits<decltype(&T::operator())>
    {};

    // lambda / functor
    template <class ClassType, class ReturnType, class... Args>
    struct callable_traits<ReturnType(ClassType::*)(Args...) const>
    : detail::callable_traits_base<ReturnType, Args...>
    {};
    struct Hash {
    uint32_t operator ()(const char *buffer, size_t n) const {
    return 65;
    }
    };

    static_assert(std::is_same<callable_traits<Hash>::return_type, uint32_t>::value, "");
    static_assert(std::is_same<callable_traits<Hash>::argument_type, std::tuple<const char *, size_t>>::value, "");

    Online demo

    您可以查看 callable_traits 的完整实现 here

    关于c++11 - 仿函数的编译时检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33885420/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com