operator specifer, not just a name.
When I was trying to write the following code:
#include <iostream>
template <class T>
struct Foo {
T obj;
};
#define DEF_B_OP_TP(OP) \
template <class T1, class T2>\
auto operator##OP (const Foo<T1> &t1, const Foo<T2> &t2) noexcept -> Foo<decltype(t1.obj + t2.obj)>\
{ return {t1.obj + t2.obj}; }
DEF_B_OP_TP(+)
template <class Stream, class T>
Stream&& operator<<(Stream &&s, const Foo<T> &t) { return static_cast<Stream&&>(s << t.obj); }
int main() {
std::cout << (Foo<int>{0} + Foo<int>{10}) << std::endl;
return 0;
}
After compiling with clang++-3.5 -std=c++14(same output when using clang++-5.0 -std=c++14),it gives the following messages from clang:
operator_specifer.cc:10:1: error: pasting formed ‘operator+’, an invalid preprocessing token DEF_B_OP_TP(+)
operator_specifer.cc:8:14: note: expanded from macro ‘DEF_B_OP_TP’ auto operator##OP (const Foo
&t1, const Foo &t2) noexcept -> Foo<decltype(t1.obj + t2.obj)>\ ^ 1 errors generated.
which is quite confusing to me. So I do some searching on Stackoverflow, and I found this Why string concat macro doesn’t work for this “+” case?, it mainly tells me 2things:
-
operator is not a name when defining or declaraing a function, it is a specifier. So, instead of writing
operator+
, we should writeoperator +
. And that explain why I can writeoperator Type
,operator auto
,template <class T> operatpr T
and sth. like:#include <iostream> #define OUTPUT() std::cout << __PRETTY_FUNCTION__ << std::endl struct Foo { ~ Foo() { OUTPUT(); } }; template <class T> void destroy_at(const T *p) { p-> ~ T(); }//actually a func like this is defined in c++17 stdard header memory int main() { Foo *p = new Foo; destroy_at(p);//Foo::~Foo() return 0; }
So here I should replace the macro with the following code:
#define DEF_B_OP_TP(OP) \ template <class T1, class T2>\ auto operator OP (const Foo<T1> &t1, const Foo<T2> &t2) noexcept -> Foo<decltype(t1.obj + t2.obj)>\ { return {t1.obj + t2.obj}; }
And it works.