对std :: tuple-like的命名要求?

时间:2019-01-08 21:50:35

标签: c++ tuples stdtuple

我当时正在为std::tuple开发一种通用的哈希算法,并意识到我也可以使其适用于std::pairstd::array,因为这三个类实现了std::tuple_sizestd::get。这在任何地方都“标准化”了吗?除了类std :: tuple的类而不是类std :: allocator的类,是否有一个“ std::allocator_traits”?

目前,我正在这样做,以检查类是否为“类似元组”:

#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 {};
}

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

这些是我对“类似元组”类型,“ T”类型和T类型的对象t施加的“要求”:

  1. std::tuple_size<T>是完整类型
  2. std::tuple_size<T>::valuestatic constexpr const std::size_t(称为N
  3. std::get<I>(t)对于[I0)中的所有N返回非无效

(这是正确和完整的吗?我还实现了std::get的检查,但是代码发布时间太长了)

此外,除了专门化std::tuple_size<T>(也许像iterator_tag之类的东西)之外,还有一种更好的方法来指定类型是否为“元组式”

1 个答案:

答案 0 :(得分:0)

  

这个“标准化”在任何地方吗?

如果您指的是哈希算法,那么boost中已经有一个完整的解决方案。

与p ++标准本身的各种实现相比,

boost当然可以说是更加标准化和肯定地更具可移植性 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 这将被许多人视为有争议的陈述。尽管如此,从经验上讲它是正确的。