简体   繁体   English

将auto与生成元组的可变参数模板一起使用

[英]Using auto with variadic templates that generates a tuple

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 但是它没有生成任何数据,我无法弄清楚哪里出了问题,但是,我的ostream<<()正在生成编译器错误,抱怨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<<() . 我接受了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'; } 

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. 这抱怨说Is需要扩展,好吧,所以我尝试在print...函数中扩展它,并且我尝试将...运算符放在多个位置,并且似乎没有任何编译。 I'm not sure how to expand Is in this context, or if I can even use fold expressions. 我不确定在这种情况下如何扩展Is ,或者甚至是否可以使用fold表达式。

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::get无法像您那样使用的原因。

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. 如果要遍历元组的元素,我建议使用std::apply ,它是专门为这样做而设计的。 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM