我的基本想法是从std::tuple派生我自己的类,以便在里面获得一些helper类型,如下所示:
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...>;
};
现在我尝试使用如下代码:
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 );
}
线条
MyType_tuple_with_empty p1{{{ 1.2,3},{},{1}}};
MyType_tuple_non_empty p3{{ 1.2,3},{4},{1}};
不能用GCC5.2.0编译,而是用GCC6.1.0编译。这有点神秘,因为我记得元组的构造函数确实是显式的。为什么这适用于GCC6.1.0?但这不是我寻找的问题:-)
另一个提示:我遇到问题的代码似乎是用Clang3.5.0编译的。
不幸的是,您必须添加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));
}
只需在do
类函数中使用get
而不是std::get
。编译器能够从参数中选择命名空间。
我想,我不确定,这是因为gcc在其元组中实现了EBO-空基优化。确切的原因是什么,很难猜测。您可以考虑在gcc Bugzilla中报告这一点。
顺便说一句,从STD类派生不是一个好习惯。如果从compisition开始,而不是从继承开始,则需要提供自己的get
函数,这样就不会发现这个错误,可能会节省大量时间。
在godbolt.org中编译代码时,我遇到以下错误: 看起来该错误是在使用std::thread创建线程时出现的。该守则的简化版本为:
有时,我想通过一个真正的类来更改我定义的类型。 例如,我在这里举了一个例子,如何以与类型相同的方式使用结构: 这工作正常。 但是:由于任何原因,相同的代码不适用于std::元组,即这会产生编译错误: 有人知道为什么会这样吗? 有办法解决这个问题吗? 我用clang、gcc和msvc在编译器资源管理器上测试了这个。 感谢您的帮助, 问候, 佐波
以下代码片段适用于Visual Studio 2008,但不适用于Visual Studio 2010。 用法 我得到以下错误: 1个 如果用typedef int MyValueType替换typedef STD::tr1::tuple myvalue type,则有效。 提前感谢您。
首先,我确实在谷歌上做了一个快速搜索,没有一个解释我拍摄的目的。 我的问题是如何在成员函数中访问该消息,例如(中的虚函数)?父类中没有定义或类似的函数,如果调用恰好是我要重写的函数,那么调用该函数是非常没用的。 我使用的是Visual Studio Community 2015,因此编译器特定的方法是可以的,但我更喜欢可移植的解决方案。
我正在运行一个调用shell脚本的程序(用于讨论带有pid 100的sh1)。该脚本依次调用另一个脚本(用于与pid 101的讨论sh2),并等待它完成。sh2(子脚本)完成大约需要50秒。 调用sh2的方式(/bin/sh2.sh) 在等待子进程完成期间,我尝试终止sh1(使用kill-15 100)。我在sh1中有一个处理程序函数来处理此信号。但是,我观察到我的sh1(父脚本)直到子进程完成其