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
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;
}
Edit
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';
}
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.