std::tuple-like 的命名要求? [英] Named requirement for std::tuple-like?

查看:35
本文介绍了std::tuple-like 的命名要求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 std::tuple 制作一个通用哈希算法,并意识到我可以让它适用于 std::pairstd::array 也是如此,因为这三个类实现了 std::tuple_sizestd::get.这是标准化"的地方吗?是否有std::allocator_traits"但对于 std::tuple-like 类而不是 std::allocator-like 类?

I was making a generic hash algorithm for std::tuple, and realised I could make it work for std::pair and std::array as well, as these three classes implement std::tuple_size and std::get. Is this "standardised" anywhere? Is there a "std::allocator_traits" but for std::tuple-like classes instead of std::allocator-like classes?

目前我这样做是为了检查一个类是否是类元组":

Currently I am doing this to check if a class is "tuple-like":

#include <type_traits>
#include <cstddef>
#include <utility>
#include <tuple>

namespace is_tuple {
    namespace detail {
        // T* exists for incomplete types, but not sizeof(T)
        template<class T, ::std::size_t = sizeof(T)>
        ::std::true_type is_complete_type_impl(T*);

        ::std::false_type is_complete_type_impl(...);

        template<class T>
        struct is_complete_type : decltype(
            is_complete_type_impl(::std::declval<T*>())
        ) {};
    }

    template<class T>
    struct is_tuple : detail::is_complete_type<::std::tuple_size<T>>::type {};
}

这可能有一些误报(尽管我认为不会)

This might have some false positive (though I don't think it does)

这些是我对类元组"类型、类型 T 和名为 t<的 T 类型的对象强加的要求"/代码>:

These are the "requirements" I am imposing for "tuple-like" types, for a type T and an object of type T called t:

  1. std::tuple_size 是一个完整的类型
  2. std::tuple_size::value 是一个 static constexpr const std::size_t(称为 N)
  3. std::get(t) 为 [0, N<中的所有 I 返回非空值/code>)
  1. std::tuple_size<T> is a complete type
  2. std::tuple_size<T>::value is a static constexpr const std::size_t (called N)
  3. std::get<I>(t) returns non-void for all I in [0, N)

(这是否正确和完整?我也实现了检查std::get,但代码太长无法发布)

(Is this correct and complete? I also implemented checking std::get, but the code was too long to post)

此外,除了专门化 std::tuple_size(可能类似于 iterator_tag)

And also, is there a better way to specify if a type is "tuple-like" other than specialising std::tuple_size<T> (Something like an iterator_tag maybe)

推荐答案

这在任何地方都标准化"了吗?

Is this "standardised" anywhere?

如果你指的是散列算法,那么(像很多事情一样)在 boost 中已经有一个完整的解决方案.

If you mean the hash algorithm, then (like so many things) there is already a complete solution in boost.

boost 当然可以说比 C++ 的各种实现更标准化,当然更便携标准本身.1

boost is of course, arguably more standardised and certainly more portable than the various implementations of the c++ standard itself.1

#include <boost/functional/hash.hpp>
#include <tuple>
#include <utility>
#include <array>
#include <string>
#include <iostream>

template<class T>
std::size_t hashit(T const& x)
{
    using x_type = std::decay_t<T>;
    return boost::hash<x_type>()(x);
}

template<class T>
std::size_t hashit2(T const& x)
{
    using boost::hash_value;
    return hash_value(x);
}

int main()
{
    using namespace std::literals;

    std::cout << hashit(std::make_tuple(1, 2, 5, "foo"s)) << '\n';
    std::cout << hashit2(std::make_tuple(1, 2, 5, "foo"s)) << '\n';

    std::cout << '\n';

    std::cout << hashit(std::make_pair(1.0, 2.0)) << '\n';
    std::cout << hashit2(std::make_pair(1.0, 2.0)) << '\n';

    std::cout << '\n';

    std::cout << hashit(std::array<int, 3>{4, 5, 6}) << '\n';
    std::cout << hashit2(std::array<int, 3>{4, 5, 6}) << '\n';
}

1 这将被许多人视为有争议的声明.尽管如此,它在经验上是正确的.

1 This will be seen by many as a controversial statement. It is nonetheless empirically true.

这篇关于std::tuple-like 的命名要求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆