Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将std::tuple转换为模板参数包_C++_C++11_Tuples_Variadic Templates - Fatal编程技术网

C++ 将std::tuple转换为模板参数包

C++ 将std::tuple转换为模板参数包,c++,c++11,tuples,variadic-templates,C++,C++11,Tuples,Variadic Templates,我有一个 typedef std::tuple<A, B> TupleType; typedef std::tuple TupleType; 并希望使用类列表 对于“模板” 假设我有: template<typename... args> std::tuple<args...> parse(std::istream &stream) { return std::make_tuple(args(stream)...); } 模板 std::tu

我有一个

typedef std::tuple<A, B> TupleType;
typedef std::tuple TupleType;
并希望使用类列表 对于“模板”

假设我有:

template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
  return std::make_tuple(args(stream)...);
}
模板
std::tuple解析(std::istream&stream){
返回std::make_tuple(args(stream)…);
}
我可以成功地将其用于:

auto my_tuple = parse<A, B>(ifs);
auto my_tuple=parse(ifs);
如果我已经有一个类列表,是否可以避免指定类列表A,B

typedef std::tuple<A,B> TupleType;
typedef std::tuple TupleType;
列表A、B已经存在的位置

例如:

#包括//退出成功、退出失败
#包括//标准::cerr
#include//std::ifstream
#include//std::tuple
甲级{
公众:
A(std::istream&);//可能会抛出foobarexception
};
B类{
公众:
B(std::istream&);//可能会抛出FoobareException
};
模板
std::tuple解析(std::istream&stream){
返回std::make_tuple(args(stream)…);
}
int main(){
std::ifstream-ifs;
异常(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
int res=退出故障;
试一试{
打开(“/some/file/path”,std::ios::in | std::ios::binary);
auto my_tuple=parse(ifs);//my_tuple的类型为std::tuple
/*这里用我的元组做一些有趣的事情*/
res=退出成功;
}捕获(ifstream::failure e){

std::cerr基本方法是创建一系列索引
0,…,std::tuple\u size::value-1
作为参数包
索引
,并使用
parse(stream)
调用函数。您可能会将逻辑封装到一个函数
parse\u tuple(stream)
(以及此函数所委托的某些函数)最终委托给
parse(stream)

首先,这里是一个类模板和一个函数,用于根据
std::tuple
的大小创建一系列索引。从
std::tuple
获取类型列表需要索引:

template <int... Indices> struct indices;
template <> 
struct indices<-1> {                // for an empty std::tuple<> there is no entry
    typedef indices<> type;
};
template <int... Indices>
struct indices<0, Indices...> {     // stop the recursion when 0 is reached
    typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...> { // recursively build a sequence of indices
    typedef typename indices<Index - 1, Index, Indices...>::type type;
};

template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices() {
    return 0;
}
模板结构索引;
模板
结构索引{//对于空std::tuple,没有条目
类型定义索引类型;
};
模板
结构索引{//在达到0时停止递归
类型定义索引类型;
};
模板
结构索引{//递归地构建索引序列
typedef typename索引::type type;
};
模板
类型名索引::类型常量*
制作索引(){
返回0;
}
有了它,就很容易从
std::tuple
中提取类型序列:

template <int... Indices> struct indices;
template <> 
struct indices<-1> {                // for an empty std::tuple<> there is no entry
    typedef indices<> type;
};
template <int... Indices>
struct indices<0, Indices...> {     // stop the recursion when 0 is reached
    typedef indices<0, Indices...> type;
};
template <int Index, int... Indices>
struct indices<Index, Indices...> { // recursively build a sequence of indices
    typedef typename indices<Index - 1, Index, Indices...>::type type;
};

template <typename T>
typename indices<std::tuple_size<T>::value - 1>::type const*
make_indices() {
    return 0;
}
模板
T解析元组(std::istream&stream,索引常量*){
返回解析(流);
}
模板
T解析元组(std::istream&stream){
返回parse_元组(stream,make_index());
}

这类事情有一个标准的习惯用法。[1]

// Define the "shape" of the template
template<typename Tuple> struct TupleMap;
// Specialize it for std::tuple
template<typename...T> struct TupleMap<std::tuple<T...>> {
  using type = std::tuple<T...>;  // not necessary but saves typing
  // ... inside here, you have access to the parameter pac
}

[1] 至少,我认为这是一个标准的习语。我经常使用它,并将其视为“开罐器”模式

[2] 这是需要的(或者至少,这是我的风格)允许将
get
std
之外定义的元组模板一起使用。这样做可以让ADL找到
get
的适当定义,而无需强迫我向
std::get
添加专门化。这样,它类似于
开始
结束
的标准ADL习惯用法。


[3]您可以搜索一种专门化
运算符的酷方法。在您的情况下,潜在的问题似乎是,对于模板参数为
std::tuple
的特殊情况,您希望专门化函数模板
parse
。不幸的是,这种专门化在函数模板中是不可能的

但是,可以使用类模板

因此,作为第一步,您可以将
parse
定义为
struct
的静态函数,如下所示:

using std::istream;
using std::tuple;
using std::make_tuple;

struct A { A(const istream &) {} };
struct B { B(const istream &) {} };

template <typename... Args>
struct parser
{
  /* Your original function, now inside a struct.
     I'm using direct tuple construction and an
     initializer list to circumvent the order-of-
     construction problem mentioned in the comment
     to your question. */
  static tuple<Args...> parse(const istream &strm)
  { return tuple<Args...> {Args(strm)...}; }
};

template <typename... Args>
struct parser<tuple<Args...>>
{
  /* Specialized for tuple. */
  static tuple<Args...> parse(const istream &strm)
  { return parser<Args...>::parse(strm); }
};
使用std::istream;
使用std::tuple;
使用std::make_tuple;
结构A{A(const-istream&){};
结构B{B(const-istream&){};
模板
结构分析器
{
/*您的原始函数,现在位于结构中。
我使用直接元组构造和
绕过-
评论中提到的施工问题
回答你的问题*/

静态元组。

在构造函数中,您似乎希望从字符串中读取。请注意,对于
parse
@johanneschaub-litb的实现,构造函数的调用顺序是未指定的,有趣的一点。如果组件类型不同,也可以这样做(可能的但太长,不能显示为重复类型的例子)。7年后……考虑C++ 17。+ 1,用于使用结构的专门化。(我发布自己答案的原因是,我认为OP代码中的
parse
函数应该转换为结构的静态函数,而不是调用结构的构造函数。)@jogojapan是合法的设计决策。虽然我不认为这有多大区别。但品味不同。你可能想考虑litb关于构造顺序的观点,除非你已经看过我在lws上的版本。“不幸的是,这种专门化在函数模板上是不可能的。”不完全正确。嗯,这是正确的,但是你可以从重载和模板推断中获得大致相同的效果。请看这里:@rici我认为你不能使用重载解决问题中描述的问题,因为现有版本的
解析
,必须保持完整,非常通用,会导致歧义是的。但是用于结构/类的机制是部分模板专门化,这可以实现上述的消歧。TBH,我不知道他想做什么。我读了好几遍这个问题,我仍然不明白他想展示什么接口。但是,使用addi的演绎肯定是可能的解析未赋值的参数,这有时是一种有用的技术
using std::istream;
using std::tuple;
using std::make_tuple;

struct A { A(const istream &) {} };
struct B { B(const istream &) {} };

template <typename... Args>
struct parser
{
  /* Your original function, now inside a struct.
     I'm using direct tuple construction and an
     initializer list to circumvent the order-of-
     construction problem mentioned in the comment
     to your question. */
  static tuple<Args...> parse(const istream &strm)
  { return tuple<Args...> {Args(strm)...}; }
};

template <typename... Args>
struct parser<tuple<Args...>>
{
  /* Specialized for tuple. */
  static tuple<Args...> parse(const istream &strm)
  { return parser<Args...>::parse(strm); }
};
int main()
{
  typedef tuple<A,B> tuple_type;
  auto tup = parser<tuple_type>::parse(std::cin);
  return 0;
}
template <typename... Args>
auto parse(const istream &strm) -> decltype(parser<Args...>::parse(strm))
{ return parser<Args...>::parse(strm); }
int main()
{
  typedef tuple<A,B> tuple_type;
  auto tup = parse<tuple_type>(std::cin);
  return 0;
}