gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 16:37:41 25 4
gpt4 key购买 nike

我有一个

typedef std::tuple<A, B> TupleType;

并且想使用类列表对于"template"。

假设我有:

template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}

而且我可以成功地将它用于:

auto my_tuple = parse<A, B>(ifs);

如果我已经有一个,是否可以避免必须指定类列表 A、B

typedef std::tuple<A,B> TupleType;

列表 A、B 已经存在于何处?

一个例子:

#include <cstdlib>  // EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
#include <tuple> // std::tuple

class A {
public:
A(std::istream &); // May throw FooBaarException
};

class B {
public:
B(std::istream &); // May throw FooBaarException
};

template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}

int main() {
std::ifstream ifs;
ifs.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
int res = EXIT_FAILURE;
try {
ifs.open("/some/file/path", std::ios::in | std::ios::binary);
auto my_tuple = parse<A, B>(ifs); // my_tuple is of the type std::tuple<A,B>
/* Here do something interesting with my_tuple */
res = EXIT_SUCCESS;
} catch (ifstream::failure e) {
std::cerr << "error: opening or reading file failed\n";
} catch (FooBaarException e) {
std::cerr << "error: parsing in a constructor failed\n";
}
return res;
}

最佳答案

你的情况的根本问题似乎是你想专门化函数模板 parse对于模板参数为 std::tuple 的特殊情况.不幸的是,函数模板无法实现这种特化。

但是,类模板是可能的。

因此,作为第一步,您可以定义 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); }
};

然后您可以以所需的方式调用它:

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;
}

(您仍然可以按照旧方式使用它:auto tup = parse<A,B>(std::cin)。)


备注。正如在对 parser::parse() 的评论中提到的,我使用了直接元组构造而不是 make_tuple。以避免元组元素的构造顺序出现问题。这与您的问题没有直接关系,但却是一件好事。参见 how to avoid undefined execution order for the constructors when using std::make_tuple .

关于c++ - 将 std::tuple 转换为模板参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14033828/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com