为运营商创建宏<<

时间:2018-01-23 11:55:30

标签: c++

我知道使用宏“通常”不被认为是良好的编程习惯,但我想知道如何为运营商定义宏。例如,几个boost库具有可用作(http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/sources.html)的宏:

BOOST_LOG(m_logger)<< "Message to log";

我试图查看BOOST_LOG的定义,但这也指向一个不同的宏,它也指向另一个等,直到我到达:

#define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\
    for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\
        ::boost::log::aux::make_record_pump((logger), rec_var).stream()

我的问题是,如果我有一个运算符&lt;&lt;在课堂上,我怎么能把它变成一个微观,所以我可以做:

MY_MACRO&lt;&lt;消息。

3 个答案:

答案 0 :(得分:4)

是的,你可以这样做。

MY_MACRO会评估一个类的实例化,比如Foo

在预处理器完成其工作后,MY_MACRO << message变为Foo() << message;

Foo然后为<<等类型定义了一个重载的const char*运算符,它会累积结果。此外,Foo有一个析构函数,它实际上输出了那些累积的结果。一旦匿名临时Foo超出范围,将在语句结束时调用此方法。

答案 1 :(得分:1)

正如您所指出的,在C ++中通常最好避免使用宏。

然而,放纵你的好奇心(我不推荐这样的事情)......

为此,宏需要(最终)扩展为(1)范围内的现有对象的名称(或可能是对其的引用)或(2)实例化对象的表达式。 / p>

在这两种情况下,对象都必须是具有合适operator<<()的类型。

第一个例子是

 #include <iostream>

 #define A_MACRO std::cout

 int main()
 {
     A_MACRO << "Hello world\n";    // will write to std::cout
 }

第二部分的部分例子是

 class X
 {
      public:

         X() {  /*  set things up */ };

         X &operator<<(const char * s)
         {
               // do something with s

               return *this;
         };

         ~X()
         {
             // clean up whatever resources (file handles, etc) the constructor set up
         };
 };

 #define B_MACRO(SOMETHING)  SOMETHING()

 int main()
 {
       B_MACRO(X) << "Hello world\n";
 }

(这是部分的,因为X可能需要做一些我尚未实施的有用的东西。此示例要求宏参数是既具有默认参数又具有合适operator<<()的类型。 operator<<()可以是某个类的成员(如上所述),非成员友元函数或仅访问X的公共成员的非成员函数

为了更好地理解,请阅读预处理器的工作原理(例如,如何处理扩展为使用其他宏的宏,以及它如何处理宏参数)。

实际上,尽量避免在C ++中这样做,你需要的场合很少见(例如,如果你正在编写像Boost一样的库,必须适用于具有不同特性和错误的一系列编译器)。宏有一堆不良特征,包括忽略范围。你通常最好直接使用对象或类型,而不是将它们的用法隐藏在一组宏中。

答案 2 :(得分:0)

在创建宏时,您不能使用字母,数字和美元符号以外的字符(标准不支持这些字符)。你正在谈论的库可能会将它收到的任何参数包装到一个带有重载&gt;&gt;的类中。操作

例如:

class wrapper {
    int convertedType[];
    public:
        wrapper(aClassType a) {
            //Convert a to an array of integers
        }

        static wrapper createWrapper(aClassType a) {
            //Do the same thing as the constructor
        }

        aClassType toOriginalType(wrapper a) {
            //perform conversion to wrapper
        }

        operator<< {
            //perform operations on the converted type (int array in this example
        }
}

#define MACRO(x) wrapper::toOriginalType(wrapper::createWrapper(x) << 5)

如果您创建了足够的转化方法,那么它就好像&gt;&gt;可以在宏中使用。