c++ - 将 auto 与生成元组的可变参数模板一起使用
问题描述
我已经为此工作了一段时间,我发现这个Q/A 是我如何存储元组的一个很好的答案。现在我正在尝试使用一个函数模板来生成这个类和 auto 关键字来生成这个对象的实例。我没有收到任何编译器错误;但它没有生成任何数据,我无法弄清楚我哪里出错了,但是,我ostream<<()
正在生成编译器错误,抱怨std::get
这是我的课程以及我尝试使用它的一些方法。
#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<<()
.
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';
}
这抱怨Is
需要扩展,好吧,所以我尝试在print...
函数中扩展它,我尝试将...
运算符放在多个位置,但似乎没有任何编译。我不确定如何Is
在这种情况下扩展,或者我什至可以使用折叠表达式。
解决方案
正如评论中提到的,非类型模板参数需要编译时常量表达式。这就是为什么std::get
不能像你那样使用。
如果您想遍历元组的元素,我建议您使用std::apply
专门为此而设计的。您的代码的可能重新实现将是:
#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;
}
推荐阅读
- docker - 集成两个 docker 应用 - Docker compose 和 Docker run
- php - ErrorException 未定义变量:post
- c# - 列表集合 addRange 多个项目
- c++ - Problem in testing my function with Catch2Farmework
- r - 如何给向量一个单一的名称,就好像它是 data.frame 的一列?
- reactjs - 防止来自处理程序的未安装组件的状态更新警告的最佳实践
- python-3.x - 有人知道修复这个错误吗?我不知道这是关于学校的便条
- java - 在 Python/Java 服务器/客户端之间发送对象
- java - 在 Mono 的阻塞线程上执行转换步骤
- python - 如何修复我的敌人不会消失的错误?