将不同类型的多个参数发送到处理方法的最佳方法。 C ++

时间:2017-06-23 18:35:49

标签: c++

目前我有一个方法如下:

std::stringstream ss; ss << "lives:" << this->Lives;
Text->RenderText(ss.str(), font, x, y, scale,color);

现在这对我来说似乎很混乱,我想把它减少到一行。 但我似乎无法想出一种干净利落的方法。

我想过使用varidic函数,但这限制了我一种类型,我必须指定参数的数量。

此外,虽然使用了std :: initializer_list或varidic模板,但它看起来并不好看。

在此解决方案中:Here Georg Fritzsche提供的答案显示了一个可行的解决方案:

helper() << a << b << c;

但实际执行它我不确定。

类似于:

Text->render(font, x, y, scale,color) << "lives:" << this->Lives;

会很好,但在方法中我不确定如何定义它。

我无法返回一个stringstream对象,因为我无法在返回后访问它。

那么如何用链接&lt;&lt;这样的方法呢?工作?

2 个答案:

答案 0 :(得分:3)

返回一个临时对象,它累积字符串的所有部分,然后在语句结束时自动销毁它,让它在析构函数中呈现内容。

#include <utility>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;

class Renderer {
    stringstream sstream;
    float x;
    float y;
public:
    Renderer(float x, float y) : x(x), y(y){}
    template<class T>
    Renderer && operator<<(T&& t) {
        sstream << std::forward<T>(t);
        return std::move(*this);
    };
    ~Renderer() {
        // your real code replaces the line below..
        cout << sstream.str() << endl;
    }
};

Renderer render(float x, float y) {
    return Renderer(x, y);
}

int main() {
    int i = 5;
    render() << "foo" << i;
}

直播:https://wandbox.org/permlink/UToweQELJ4jt0QYl

答案 1 :(得分:-1)

我如何处理这个

好的,你有这个:

std::stringstream ss; ss << "lives:" << this->Lives;
Text->RenderText(ss.str(), font, x, y, scale,color);

现在,如果您真的想在一行中完成,为什么不将字符串生成放入单个函数调用中,具体如

std::string life_text(int lifecount){
   std::stringstream ss;
   ss<<"lives:"<<lifecount;
   return ss.str();
}

所以你可以像这样调用渲染:

Text->render(life_text(lives), x, y, scale,color);

您正在寻找什么

首先,在我回答您提出的问题之前,<<运算符并不意味着方法链接。至少在香草C ++中没有,事实上,我不认为它在c ++中的任何地方使用过。

流对象并不是真正链接一个方法,而是调用

之类的东西
template<typename T> std::stringstream& operator<<(std::stringstream& rightside,T leftside){
    rightside.append(leftside);
    return rightside;
}

那么在每一步中发生的事情都是这样的:

stringstream r;
r<<"lives:";
r<<this->lives;

你所要求的并非如此简单。您需要更改rendertext函数以返回可以传递参数的新类型的对象。这很难。

其次,这意味着您的评估订单会使这更具挑战性。有办法解决这个问题,但我不知道这种情况是否会像上面那样简单的便利功能不会更好。

如果您已经这样做了,那么您可能不得不做一些非常有问题的事情。您必须使对象调用实际的渲染函数(我假设您可能已经从某个框架中获得)。

很好,但是现在您需要添加一些可能很重要的范围,如果您需要按特定顺序完成此操作。看起来可能是这样的:

{
    Text->render(x,y,scale,color)<<"lives:"<<this->Lives;
}

在我看来,这看起来很令人沮丧。

如果您愿意,我会回答您有关我的答案的任何问题,但至少在我看来,您原来的目标似乎是在咆哮着错误的树你是怎么想这样做的。

以您想要的方式接近解决方案

template<std::function<typename ReturnType(std::string&,typename Ts...)> Func>
class caller{
std::stringstream r;
Ts... arguments;
Func storedFunction;
public:

caller(Func x,typename Ts...):storedFunction(x){
arguments=Ts;

}
~caller(){
Func(r.str(),...Ts);
}
friend template<typename S,typename P> caller<S>& operator<<(caller<S>&,T value);
};
template<typename S,typename P> caller<S>& operator<<(caller<S>& c, T value){
    c.r<<value;
}

caller a_suitable_name(std :: bind(&amp; Text :: Render,&amp; Text),_ those_other_arguments);    呼叫者LT;&LT;&#34;住:&#34;&LT;

这不可能以目前的形式发挥作用,但我没有时间完成定义。