元组和可变参数模板,这是如何工作的
Tuple and variadic templates, how does this work?
我见过人们写(关于堆栈溢出本身,询问一些甚至高级概念)如下的内容:
template<typename... args>
std::tuple<args...> parse(istream stream)
{
return std::make_tuple(args(stream)...);
}
并将其用作
auto tup = parse<int, float, char>(stream);
上面的代码如何通过解析流来构造元组?对于如何将数据放入流中是否有任何具体要求?
必须从 std::istream
隐式转换为指定为模板参数的所有类型。
struct A {
A(std::istream&) {} // A can be constructed from 'std::istream'.
};
struct B {
B(std::istream&) {} // B can be constructed from 'std::istream'.
};
int main() {
std::istringstream stream{"t1 t2"};
auto tup = parse<A, B>(stream);
}
它通过扩展类型的可变参数列表来工作,并使用提供的std::istream
作为参数构造每个类型。然后留给每种类型的构造函数从流中读取。
另请注意,构造函数的求值顺序未指定,因此您不能期望可变参数列表中的第一种类型首先从流中读取等。
代码本身不适用于内置类型,如int
、float
和char
,因为没有从std::istream
到任何这些类型的转换。
它工作得很差。 它依赖于具有采用std::istream
的构造函数的目标类型。
由于许多类型没有这个,你不能把它添加到类似的东西int
,这是一个糟糕的计划。
而是这样做:
template<class T>
auto read_from_stream( std::istream& stream, T* unused_type_tag )
-> typename std::decay<decltype( T{stream} )>::type
{
return {stream};
}
template<class T>
auto read_from_stream( std::istream& stream, T* unused_type_tag, ... )
-> typename std::decay<decltype( T(stream) )>::type
{
return T(stream);
}
template<typename... args>
std::tuple<args...> parse(std::istream& stream) {
return std::tuple<args...>{
read_from_stream(stream, (args*)nullptr)...
};
}
现在我们不是直接构造参数,而是调用 read_from_stream
。
read_from_stream
上面有两个重载。 第一个尝试从istream
直接和隐式地构造我们的对象。 第二个从istream
显式构造我们的对象,然后使用 RVO 返回它。 ...
确保仅在第一个失败时使用第二个。
无论如何,这打开了一个定制点。 在类型X
的命名空间中,我们可以编写一个read_from_stream( std::istream&, X* )
函数,它将被自动调用,而不是上面的默认实现。 我们还可以编写read_from_stream( std::istream&, int* )
(等),它可以知道如何从istream
解析整数。
这种自定义点也可以使用 traits 类来完成,但使用重载执行此操作具有许多优点:您可以注入与类型相邻的自定义项,而不必打开完全不同的命名空间。 自定义操作也更短(没有类包装噪音)。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?