C++ 使用C++;元组类型作为映射中的键

C++ 使用C++;元组类型作为映射中的键,c++,loops,tuples,sfinae,c++14,C++,Loops,Tuples,Sfinae,C++14,我试图将不同类型的值集合映射到连续空间中。要做到这一点(有效),我需要知道所有元素的总大小和每个元素的偏移量。若集合以元组形式给出,则获取总大小很容易。它还允许预先计算偏移。我很难用字体来抵消。为了简化示例,我假设元组中的类型是唯一的(实际上,元组将有两对唯一标记+非唯一值)。以下是我当前未编译的尝试: #include <cstddef> #include <iostream> #include <tuple> struct A { std::si

我试图将不同类型的值集合映射到连续空间中。要做到这一点(有效),我需要知道所有元素的总大小和每个元素的偏移量。若集合以元组形式给出,则获取总大小很容易。它还允许预先计算偏移。我很难用字体来抵消。为了简化示例,我假设元组中的类型是唯一的(实际上,元组将有两对唯一标记+非唯一值)。以下是我当前未编译的尝试:

#include <cstddef>
#include <iostream>
#include <tuple>

struct A
{
    std::size_t size()
    {
        return 3;
    }
};

struct B
{
    std::size_t size()
    {
        return 2;
    }
};

struct C
{
    std::size_t size()
    {
        return 4;
    }
};

template <typename Tuple>
struct Foo
{
    const Tuple& tuple_;
    std::array<int, std::tuple_size<Tuple>::value> array_;

    Foo(const Tuple& tuple) : tuple_(tuple)
    {
        std::cout << init() << '\n';
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////

    template <std::size_t INDEX = 0>
    typename std::enable_if<std::tuple_size<Tuple>::value == INDEX, std::size_t>::type
    init()
    {
        return 0;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////

    template <std::size_t INDEX = 0>
    typename std::enable_if<std::tuple_size<Tuple>::value != INDEX, std::size_t>::type
    init()
    {
        auto offset = init<INDEX + 1>();

        std::cout << "index: "<< INDEX << "; offset: " << offset << '\n';

        array_[INDEX] = offset;

        return offset + std::get<INDEX>(tuple_).size();
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////

    template <std::size_t INDEX = 0, typename T>
    typename std::enable_if<std::tuple_size<Tuple>::value == INDEX, std::size_t>::type
    offset(const T&)
    {
        return 0;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////

    template <std::size_t INDEX = 0, typename T>
    typename std::enable_if<(std::tuple_size<Tuple>::value != INDEX) && !std::is_same<typename std::tuple_element<INDEX, Tuple>::type, T>::value, std::size_t>::type
    offset(const T& t)
    {
        return offset<INDEX + 1>(t);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////

    template <std::size_t INDEX = 0, typename T>
    typename std::enable_if<(std::tuple_size<Tuple>::value != INDEX) && std::is_same<typename std::tuple_element<INDEX, Tuple>::type, T>::value, std::size_t>::type
    offset(const T&)
    {
        return array_[INDEX];
    }    
};

int main()
{
    A a;
    B b;
    C c;
    auto t = std::tie(a, b, c);
    using T = decltype(t);
    Foo<T> foo(t);

    std::cout << foo.offset(a) << '\n';
    //std::cout << foo.offset(b) << '\n';
    //std::cout << foo.offset(c) << '\n';
}
#包括
#包括
#包括
结构A
{
std::size\u t size()
{
返回3;
}
};
结构B
{
std::size\u t size()
{
返回2;
}
};
结构C
{
std::size\u t size()
{
返回4;
}
};
模板
结构Foo
{
常量元组和元组;
std::数组;
Foo(常量元组和元组):元组(元组)
{

std::cout看起来您想要的是:

template <typename T, typename Tuple> struct get_index;

template <typename T, typename... Ts>
struct get_index<T, std::tuple<T, Ts...>> : std::integral_constant<std::size_t, 0> {};

template <typename T, typename Tail, typename... Ts>
struct get_index<T, std::tuple<Tail, Ts...>> :
    std::integral_constant<std::size_t, 1 + get_index<T, std::tuple<Ts...>>::value> {};
模板结构获取索引;
模板
结构get_索引:std::integral_常量{};
模板
结构获取索引:
积分常数{};
然后将所有偏移方法替换为

template <typename T>
std::size_t
offset(const T&)
{
    return array_[get_index<T&, Tuple>::value];
}
模板
标准:尺寸
偏移量(常数T&)
{
返回数组[get_index::value];
}


请注意,在您的示例中,
Tuple
std::Tuple
,您使用
A

测试代码是否正确,只有一个问题除外

问题在于,您使用
std::tie()
helper函数构造了一个
std::tuple
,这将产生一个引用的元组-
std::tuple:

std::相同,T>::值
//           ~~~~~~~~~~~~^                                                      ^

C++1y,你可以简单地做一些像
(size\u t)((void*)&tuple-(void*)&std::get(tuple))
。否则你需要对函数进行专门化,以防止展开超过tuple的结尾。这对我来说就像是一个g++错误,基于
“错误:无效使用不完整的类型'struct std::tuple\u element'"
@cdhowie您认为tuple\u大小后面的tuple\u元素是完整类型吗?
tuple
为空是由于tuple的递归性质造成的_element@PiotrS.当我在看这个的时候,我想我把一件事和另一件事搞混了——我知道
std::tuple_元素
不是一个完整的类型,而是在看出于某种原因,我认为现在研究递归模板还为时过早。。。
template <typename T>
std::size_t
offset(const T&)
{
    return array_[get_index<T&, Tuple>::value];
}
std::is_same<typename std::decay<typename std::tuple_element<INDEX, Tuple>::type>::type, T>::value
//           ~~~~~~~~~~~~~~~~~~~^                                               ~~~~~~^
std::is_same<std::decay_t<typename std::tuple_element<INDEX, Tuple>::type>::type>, T>::value
//           ~~~~~~~~~~~~^                                                      ^