加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c 11 – 仿函数的编译时检查

发布时间:2020-12-16 07:14:28 所属栏目:百科 来源:网络整理
导读:我希望在我的代码中进行编译时检查,以确保给定的类重载()运算符,该运算符将const char *和size_t作为参数,并且其返回类型是无符号整数. 我尝试了几个从StackOverflow中获取的代码片段,但我对我编写的解决方案不满意: #include type_traits#include cstdint#
我希望在我的代码中进行编译时检查,以确保给定的类重载()运算符,该运算符将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();
}

对不起代码的长度,我尽量保持尽可能小.

这是我不喜欢我的代码:

>如果在重载()运算符时将int替换为参数列表中的size_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,size_t)>::type return_type;
                                                                                                    ^
rty.cpp:26:75: error: no type named ‘type’ in ‘class std::result_of<unsigned int (Hash::*(Hash,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_same在static_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的完整实现

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读