将auto与生成元组的可变参数模板一起使用 [英] Using auto with variadic templates that generates a tuple
问题描述
我已经为此工作了一段时间,并且发现了此问题/解答,很好地回答了我可以存储一个元组。现在,我尝试使用将生成此类和自动关键字的函数模板来生成该对象的实例。我没有收到任何编译器错误;但是它没有生成任何数据,我无法弄清楚哪里出了问题,但是,我的 ostream<<<()
正在生成编译器错误,抱怨 std :: get
I have been working on this for some time and I found this Q/A as a good answer into how I can store a tuple. Now I'm trying to use a function template that will generate this class and the auto key word to generate instances of this object. I'm not getting any compiler errors; yet it isn't generating any data and I can not figure out where I'm going wrong, however, my ostream<<()
is generating compiler errors complaining about std::get
这是我的课程,以及一些尝试使用它的方法。 / p>
Here is my class and a few ways of how I'm trying to use it.
#include <algorithm>
#include <iostream>
#include <tuple>
template<class... T>
class expression_t {
public:
std::tuple<T...> rhs;
std::size_t size = sizeof...(T);
template<class... Args>
expression_t(Args&& ...args) : rhs( std::forward<Args>(args)... ){}
std::tuple<T...> operator()() {
return hrs;
}
};
template<typename... Args>
expression_t<Args...> expression(Args... args) {
expression_t<Args...> expr(args...);
return expr;
}
template<typename... Args>
std::ostream& operator<< (std::ostream& os, const expression_t<Args...>& expr) {
for (std::size_t n = 0; n < expr.size; n++ ) {
if ( std::get<n>(expr.rhs) == '+' || std::get<n>(expr.rhs) == '-' ||
std::get<n>(expr.rhs) == '*' || std::get<n>(expr.rhs) == '/' ||
std::get<n>(expr.rhs) == '%')
os << ' ' << std::get<n>(expr.rhs) << ' ';
os << std::get<n>(expr.rhs);
}
os << '\n';
return os;
}
int main() {
double x = 0;
// example: 4x^2 + 2x
auto expr = expression( 4, x, '^', 2, '+', 2, x );
// try to print a single element from expr's tuple member
auto t = expr(); // using operator()
std::cout << std::get<2>(t); // compiles and runs but does not work
// try to print out the expression
std::cout << expr; // the ostream<<() operator fails to compile
// it is complaining about `std::get` with no matching overloaded function found
// with MSVC error C2672
return 0;
}
编辑
我接受了Igor的建议,并尝试使用cppreference的示例找到这里,这就是我为 operator<<<()$提出的想法c $ c>。
I took Igor's advice and tried to use cppreference's example found here and this is what I have come up with for my operator<<()
.
template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_expression_tuple_impl(std::basic_ostream<Ch, Tr>& os, const Tuple& t, std::index_sequence<Is...>) {
if ( (std::get<Is>(t) == '+') ||
(std::get<Is>(t) == '-') ||
(std::get<Is>(t) == '*') ||
(std::get<Is>(t) == '/') ||
(std::get<Is>(t) == '%') )
os << " " << std::get<Is>(t) << " ";
os << std::get<Is>(t);
}
template<class Ch, class Tr, class... Args>
auto& operator<<(std::basic_ostream<Ch,Tr>& os, const std::tuple<Args...>& t) {
print_expression_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os;
}
template<class... Args>
std::ostream& operator<<(std::ostream& os, const expression_t<Args...>& expr) {
return os << expr.rhs << '\n';
}
这抱怨是
需要扩展,好吧,所以我尝试在 print ...
函数中扩展它,并尝试放置 ...
运算符在多个位置,似乎没有任何编译。我不确定在这种情况下如何扩展是
,或者我什至可以使用折叠表达式。
This complains that Is
needs to be expanded, okay so I try to expand it in the print...
function and I've tried placing the ...
operator in multiple places and nothing seems to compile. I'm not sure how to expand Is
in this context, or if I can even use fold expressions.
推荐答案
如注释中所述,非类型模板参数需要编译时常量表达式。这就是为什么 std :: get
不能像以前那样使用的原因。
As mentioned in the comments, non-type template parameters need compile-time constant expressions. That’s why std::get
cannot be used the way you did.
如果要遍历元素元组,我建议使用 std :: apply
,这是专门为此设计的。
您可能会被重新实现的代码被重新实现:
If you want to iterate over the elements of a tuple, I would recommend to use std::apply
, which is specifically designed to do so.
A possible reimplementation of your code snipped would be:
#include <algorithm>
#include <iostream>
#include <tuple>
template<class... T>
class expression_t {
public:
std::tuple<T...> rhs;
std::size_t size = sizeof...(T);
template<class... Args>
expression_t(Args&& ...args) : rhs( std::forward<Args>(args)... ){}
std::tuple<T...> operator()() const { // Needs to be const to be used by the operator <<
return rhs;
}
};
template <typename T>
void Print(std::ostream& os, T x) {
os << x;
}
template <>
void Print<char>(std::ostream& os, char x) {
if ( x == '+' || x == '-' || x == '*' || x == '/' || x == '%')
os << ' ' << x << ' ';
}
template<typename... Args>
expression_t<Args...> expression(Args... args) {
expression_t<Args...> expr(args...);
return expr;
}
template<typename... Args>
std::ostream& operator <<(std::ostream& os, const expression_t<Args...>& expr) {
auto Fn = [&os](auto... x) {
(Print(os, x), ...); // Fold over a comma
};
std::apply(Fn, expr());
os << '\n';
return os;
}
int main() {
double x = 0;
// example: 4x^2 + 2x
auto expr = expression( 4, x, '^', 2, '+', 2, x );
auto t = expr();
std::cout << std::get<2>(t) << '\n'; // Prints ^ as expected
std::cout << expr;
return 0;
}
这篇关于将auto与生成元组的可变参数模板一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!