【发布时间】:2014-10-02 14:16:59
【问题描述】:
我正在尝试将不同类型的值集合映射到连续空间中。为此(有效地)我需要知道所有元素的总大小和每个元素的偏移量。如果集合作为元组给出,则获取总大小很容易。它还允许预先计算偏移量。我很难按类型获得偏移量。为了简化示例,我假设 Tuple 中的类型将是唯一的(实际上 Tuple 将具有一对唯一标签 + 非唯一值)。这是我当前的非编译尝试:
#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';
}
编译错误:
In file included from prog.cpp:3:0:
/usr/include/c++/4.8/tuple: In instantiation of ‘struct std::tuple_element<1u, std::tuple<C&> >’:
/usr/include/c++/4.8/tuple:680:12: recursively required from ‘struct std::tuple_element<2u, std::tuple<B&, C&> >’
/usr/include/c++/4.8/tuple:680:12: required from ‘struct std::tuple_element<3u, std::tuple<A&, B&, C&> >’
prog.cpp:79:22: recursively required from ‘typename std::enable_if<((std::tuple_size<_Tp>::value != INDEX) && (! std::is_same<typename std::tuple_element<INDEX, Tuple>::type, T>::value)), unsigned int>::type Foo<Tuple>::offset(const T&) [with unsigned int INDEX = 1u; T = A; Tuple = std::tuple<A&, B&, C&>; typename std::enable_if<((std::tuple_size<_Tp>::value != INDEX) && (! std::is_same<typename std::tuple_element<INDEX, Tuple>::type, T>::value)), unsigned int>::type = unsigned int]’
prog.cpp:79:22: required from ‘typename std::enable_if<((std::tuple_size<_Tp>::value != INDEX) && (! std::is_same<typename std::tuple_element<INDEX, Tuple>::type, T>::value)), unsigned int>::type Foo<Tuple>::offset(const T&) [with unsigned int INDEX = 0u; T = A; Tuple = std::tuple<A&, B&, C&>; typename std::enable_if<((std::tuple_size<_Tp>::value != INDEX) && (! std::is_same<typename std::tuple_element<INDEX, Tuple>::type, T>::value)), unsigned int>::type = unsigned int]’
prog.cpp:101:27: required from here
/usr/include/c++/4.8/tuple:680:12: error: invalid use of incomplete type ‘struct std::tuple_element<0u, std::tuple<> >’
struct tuple_element<__i, tuple<_Head, _Tail...> >
^
In file included from /usr/include/c++/4.8/tuple:38:0,
from prog.cpp:3:
/usr/include/c++/4.8/utility:84:11: error: declaration of ‘struct std::tuple_element<0u, std::tuple<> >’
class tuple_element;
^
【问题讨论】:
-
C++1y,您可以简单地执行
(size_t)((void*)&tuple_-(void*)&std::get<T>(tuple))之类的操作。否则,您需要对函数进行专门化,以防止展开超出元组的末尾。 -
这对我来说闻起来像一个 g++ 错误,基于
"error: invalid use of incomplete type ‘struct std::tuple_element<0u, std::tuple<> >’"的快速 google。 -
@cdhowie 你希望 tuple_size 后面的 tuple_element 是一个完整的类型吗?空的
tuple<>是由于 tuple_element 的递归性质造成的 -
@PiotrS。我猜想我在看这个的时候有交叉线,我把一件事弄混了——我知道
std::tuple_element<0, std::tuple<>>不是一个完整的类型,但出于某种原因正在寻找不同的类型。现在看递归模板还为时过早,我猜......