根据某些条件,使用运算符&lt; <! - ? - >打印不同类型的不同值

时间:2014-08-25 01:10:20

标签: c++

假设我想打印数字args如果它们是&gt;如果它们是&lt; = 1,则为1或“none”。我知道如何执行此操作的唯一方法是:

cout << "number of args: ";
if (argc > 1)
  cout << argc - 1;
else
  cout << "none";
cout << endl;

但是我无法链接<<运算符。理想情况下,我希望能够做到这样的事情:

cout << "number of args: "
     << argc > 1 ? argc - 1 : "none"
     << endl;

但这不可能,因为三元组的类型不同。

想法?

5 个答案:

答案 0 :(得分:5)

简单的方法。处理一个字符串。

std::cout << "number of args: "
          << (argc > 1 ? std::to_string(argc - 1) : "none")
          << std::endl;

更改字符串有一些多余的成本。但如果使用一次,它很容易阅读和维护。并且需要括号的原因是移位运算符(&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot;)具有比三元条件运算符(?:)或关系运算符(&gt;)更高的优先级。

答案 1 :(得分:4)

您可以让自己的班级进行限制打印:

class limit {
    int lim;
    int k;
public:
    limit(int lim_, int k_) : lim(lim_), k(k_) {}
    friend ostream& operator<<(ostream& ostr, const limit& lim);
};

ostream& operator<<(ostream& ostr, const limit& lim) {
    if (lim.k < lim.lim) {
        ostr << "none";
    } else {
        ostr << lim.k - lim.lim;
    }
    return ostr;
}

int main() {
    cout << "Hello " << limit(1, 15) << endl;
    cout << "World " << limit(1, -1) << endl;
    return 0;
}

Demo.

limit类包含两个数字 - 限制(演示中为1)和要打印的数字。它提供了一个用于打印的操作符<<,它使用条件语句打印超出限制的值,或"none"。这使您可以编写cout << limit(1, argc),并生成所需的打印输出。

答案 2 :(得分:3)

如果将<<放在三元表达式中,它会统一真假案例的类型。

argc > 1 ? std::cout << argc - 1 : std::cout << "none";

您可以使用辅助模板功能使事情更加无缝:

template <typename T>
std::ostream & argp (const T &x) {
    return std::cout << "number of args: " << x;
}

(argc > 1 ? argp(argc - 1) : argp("none")) << std::endl;

答案 3 :(得分:2)

如果你想要一个更通用的解决方案,你可以创建一个(模板)类来存储对两个对象和bool的引用。然后重载operator<<以根据bool选择要打印的成员。

template<typename T, typename U>
class be_careful_this_class_holds_references_to_its_constructor_arguments
{
public:
    be_careful_this_class_holds_references_to_its_constructor_arguments(
        bool b, T const& t, U const& u)
        :choose_first(b), first(t), second(u)
    {}

    friend std::ostream& operator<<(
        std::ostream& os,
        be_careful_this_class_holds_references_to_its_constructor_arguments const& p)
    {
        if (p.choose_first)
        os << p.first;
        else
            os << p.second;
        return os;
    }
private:
    bool choose_first;
    T const& first;
    U const& second;
};

使用这个类有点麻烦,你必须命名类型。您可以使用辅助函数来解决这个问题:

template<typename T, typename U>
be_careful_this_class_holds_references_to_its_constructor_arguments<T,U>
pick(bool choice, T const& first, U const& second)
{
    return be_careful_this_class_holds_references_to_its_constructor_arguments<T,U>(choice,first,second);
}

然后你可以调用这个函数,将一个条件传递给第一个参数,以及你要打印到第二个和第三个参数的两个选项:

std::cout << pick(argc > 1, argc - 1, "none") << std::endl;

答案 4 :(得分:1)

只是为了增加现有的疯狂......

支持最终使用:

xstream xs(std::cout) << If(argc <= 1) << argc - 1 << _else << "none" << _endif << '\n';

请注意,这样做 短路评估&#34; if&#34;或&#34;否则&#34;以?:;的方式进行分支,但它也不需要转换为公共类型....

实施(同样在ideone.com

#include <iostream>
using namespace std;

struct If { If(bool active) : active_(active) { } bool active_; };
struct Else { } _else;
struct Endif { } _endif;

class xstream
{
  public:
    xstream(std::ostream& os) : os_(os) { }

    template <typename T>
    friend xstream& operator<<(xstream& s, const T& t)
    {
        if (s.active_) s.os_ << t;
        return s;
    }

  private:
    bool active_;
    std::ostream& os_;
};

template <>
xstream& operator<< <If>(xstream& s, const If& _if)
{
    s.active_ = _if.active_;
    return s;
}

template <>
xstream& operator<<<Else>(xstream& s, const Else& _else)
{
    s.active_ ^= true;
    return s;
}

template <>
xstream& operator<<<Endif>(xstream& s, const Endif& _endif)
{
    s.active_ = true;
    return s;
}


int main(int argc, const char* argv[])
{
    xstream xs(std::cout);
    xs << If(argc <= 1) << argc - 1 << _else << "none" << _endif << '\n';
}

(请注意,xstream构造函数仅保留对其控制的流的引用,因此后者的生命周期必须比前者在未定义行为的惩罚下的使用寿命更长)