I'm trying to force right-associativity when using a left-associative C++ operator (like operator+()
) but I'm "dying" just before the end (see the last static_assert
).
Having some objects A a; B b; C c; D d;
and the overloaded operator+()
, I would like to write a+b+c+d
and behind the scene to have X<A, X<B, X<C,D>>>
(X being a custom binary op)
Does anybody have any hint? Or different approach?
Thanks in advance!
live example: https://godbolt.org/z/58dM6Ws4b
#include <cstdio>
#include <utility>
struct Tag{};//for class tagging
struct A: public Tag{};
struct B: public Tag{};
struct C: public Tag{};
struct D: public Tag{};
struct X0{};
template<typename L, typename R>
struct X: public X0{//binary op to force right-associativity
using TL = L;
using TR = std::conditional_t<std::is_base_of_v<Tag,L> && std::is_base_of_v<Tag,R>, R&, R>;
L& l;
TR r;
X(L&l, R&r): l{l}, r{r}{}
X(L&l, R&&r): l{l}, r{std::forward<TR>(r)}{}
X(L&&l, R&r): X{l.l, X{l.r,r}} {}
};
template<std::derived_from<Tag> L, std::derived_from<Tag> R>
auto operator+(L& l, R& r){return X{l, r};} //for: a+b
template<std::derived_from<X0> L, std::derived_from<Tag> R>
auto operator+(L&& l, R&r){return X{l.l, X{l.r,r}};} //for: a+b+c
//================================================================
int main(){
A a; B b; C c; D d;
printf("-------- a+b\n");
auto x2 = a+b;
printf("-------- a+b+c\n");
auto x3 = a+b+c; // <=> (a+b)+c
static_assert(std::is_same_v<decltype(x3), X<A, X<B,C>>>);
printf("-------- a+b+c+d\n");
auto x4 = a+b+c+d; // <=> ((a+b)+c)+d
//static_assert(std::is_same_v<decltype(x4), X<A, X<B, X<C,D>>>>); //<-- this fails
return 0;
}