Kla*_*aus 8 c++ tuples libstdc++ c++11 stdtuple
我的基本想法是从std :: tuple派生我自己的类,以获得一些内部帮助器类型:
template <typename ... T>
class TypeContainer: public std::tuple<T...>
{
public:
using BaseType = std::tuple<T...>;
static const size_t Size = sizeof...(T);
TypeContainer(T... args):std::tuple<T...>(args...){};
using index_sequence = std::index_sequence_for<T...>;
};
Run Code Online (Sandbox Code Playgroud)
现在我尝试使用如下代码:
using MyType_tuple_with_empty = std::tuple< std::tuple<float,int>, std::tuple<>, std::tuple<int>>;
using MyType_typecontainer_with_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<>, TypeContainer<int>>;
using MyType_tuple_non_empty = std::tuple< std::tuple<float,int>, std::tuple<int>, std::tuple<int>>;
using MyType_typecontainer_non_empty = TypeContainer< TypeContainer<float,int>, TypeContainer<int>, TypeContainer<int>>;
template <typename T>
void Do( const T& parms )
{
// The following lines result in errors if TypeContainer with
// empty element comes in. The empty element is in std::get<1> which
// is NOT accessed here!
std::cout << std::get<0>(std::get<0>(parms)) << " ";
std::cout << std::get<1>(std::get<0>(parms)) << std::endl;
std::cout << std::get<0>(std::get<2>(parms)) << std::endl;
}
int main()
{
MyType_tuple_with_empty p1{{ 1.2,3},{},{1}};
Do( p1 );
MyType_typecontainer_with_empty p2{{ 1.2,3},{},{1}};
Do( p2 ); // << this line raise the error
MyType_tuple_non_empty p3{{ 1.2,3},{4},{1}};
Do( p3 );
MyType_typecontainer_non_empty p4{{ 1.2,3},{4},{1}};
Do( p4 );
}
Run Code Online (Sandbox Code Playgroud)
如果我编译Do(p2)我得到以下错误:
错误:没有匹配函数来调用'
get(const TypeContainer<TypeContainer<float, int>, TypeContainer<>, TypeContainer<int> >&)'
有人可以解释为什么存在空TypeContainer的连接std::get会导致这个问题吗?
编辑:附加信息:
线条
MyType_tuple_with_empty p1{{{ 1.2,3},{},{1}}};
MyType_tuple_non_empty p3{{ 1.2,3},{4},{1}};
Run Code Online (Sandbox Code Playgroud)
不能用gcc5.2.0编译但用gcc6.1.0编译.这有点神秘,因为我记得元组的构造函数确实是显式的.为什么这适用于gcc6.1.0?但这不是我搜索的问题:-)
另一个提示:我遇到问题的代码似乎是用clang3.5.0编译的.
有点难以理解......
编辑2:挖掘错误列表(长篇:-))我发现:
/opt/linux-gnu_5.2.0/include/c++/5.2.0/tuple|832 col 5 | 注意:模板参数扣除/替换失败:main.cpp | 104 col 45 | 注意:'
std::tuple<_Elements ...>'是一个含糊不清的基类'TypeContainer<TypeContainer<float, int>, TypeContainer<>, TypeContainer<int> >'||std::cout << std::get<0>(std::get<0>(parms)) << " ";
似乎在libg ++中有人从任何元组类型派生多次,这似乎是一个破坏的库.搜索此主题将我带到:空嵌套元组错误
这真的有关系吗?相同的bug或新的:-)
不幸的是,您必须添加 get 函数的容器版本:
template <std::size_t I, typename ...T>
decltype(auto) get(TypeContainer<T...>&& v)
{
return std::get<I>(static_cast<std::tuple<T...>&&>(v));
}
template <std::size_t I, typename ...T>
decltype(auto) get(TypeContainer<T...>& v)
{
return std::get<I>(static_cast<std::tuple<T...>&>(v));
}
template <std::size_t I, typename ...T>
decltype(auto) get(TypeContainer<T...> const& v)
{
return std::get<I>(static_cast<std::tuple<T...> const&>(v));
}
Run Code Online (Sandbox Code Playgroud)
并且只是get不使用std::get某种Do功能。编译器能够从参数中选择命名空间。
我想,我不确定,这是因为 gcc 在其元组中实现了EBO(空基优化)。具体原因是什么,很难猜测。您可以考虑在gcc bugzilla中报告这一点。
顺便说一句,从 STD 类派生并不是一个好习惯。如果您从组合开始,而不是继承,那么您将需要提供自己的get函数,并且您不会观察到此错误,这可能会节省大量时间。
| 归档时间: |
|
| 查看次数: |
1729 次 |
| 最近记录: |