Code: Select all
#include
template
class IntExpr
{
public:
//typedef typename E::Type Type; //KO
static constexpr bool is_leaf = false;
template
T number() const
{
return static_cast(*this).number();
}
template
IntExpr& operator+=(T const& other)
{
*this = *this + other;
return *this;
}
};
template
class IntAdd : public IntExpr
{
typename std::conditional::type u_;
typename std::conditional::type v_;
public:
static constexpr bool is_leaf = false;
IntAdd(E1 const& u, E2 const& v) : u_(u), v_(v)
{
}
};
template
class Int : public IntExpr
{
public:
typedef T Type;
static constexpr bool is_leaf = true;
template
Int(IntExpr const& expr)
{
number_ = expr.number();
}
explicit Int(int number) : number_{number}
{
}
T number() const
{
return number_;
}
Int& operator+=(Int const& other)
{
number_ += other.number_;
return *this;
}
private:
T number_;
};
template
inline IntAdd operator+(IntExpr const& u, IntExpr const& v)
{
return IntAdd(*static_cast(&u), *static_cast(&v));
}
template * = nullptr>
inline decltype(auto) operator+(IntExpr const& lhs, S const& rhs)
{
//return lhs + Int(rhs); //KO
return lhs + T(rhs);
}
template * = nullptr>
inline decltype(auto) operator+(S const& lhs, IntExpr const& rhs)
{
//return rhs + Int(lhs); //KO
return rhs + T(lhs);
}
int main()
{
auto const a((Int(1) + 2) + 3);
auto const b((Int(1) + 2) + 3);
return 0;
}
Code: Select all
D:\programmation\cpp\TestTemplateExpression\main.cpp: In instantiation of 'decltype(auto) operator+(const IntExpr&, const S&) [with T = IntAdd; S = int; std::enable_if_t* = 0]':
D:\programmation\cpp\TestTemplateExpression\main.cpp:96:38: required from here
D:\programmation\cpp\TestTemplateExpression\main.cpp:84:18: error: no matching function for call to 'IntAdd::IntAdd(const int&)'
84 | return lhs + T(rhs);
| ^~~~~~
D:\programmation\cpp\TestTemplateExpression\main.cpp:34:9: note: candidate: 'IntAdd::IntAdd(const E1&, const E2&) [with E1 = Int; E2 = Int]'
34 | IntAdd(E1 const& u, E2 const& v) : u_(u), v_(v)
| ^~~~~~
D:\programmation\cpp\TestTemplateExpression\main.cpp:34:9: note: candidate expects 2 arguments, 1 provided
D:\programmation\cpp\TestTemplateExpression\main.cpp:26:7: note: candidate: 'constexpr IntAdd::IntAdd(const IntAdd&)'
26 | class IntAdd : public IntExpr
| ^~~~~~
D:\programmation\cpp\TestTemplateExpression\main.cpp:26:7: note: no known conversion for argument 1 from 'const int' to 'const IntAdd&'
D:\programmation\cpp\TestTemplateExpression\main.cpp:26:7: note: candidate: 'constexpr IntAdd::IntAdd(IntAdd&&)'
D:\programmation\cpp\TestTemplateExpression\main.cpp:26:7: note: no known conversion for argument 1 from 'const int' to 'IntAdd&&'
Code: Select all
:\programmation\cpp\TestTemplateExpression\main.cpp: In instantiation of 'class IntExpr':
D:\programmation\cpp\TestTemplateExpression\main.cpp:41:7: required from 'class Int'
D:\programmation\cpp\TestTemplateExpression\main.cpp:96:29: required from here
D:\programmation\cpp\TestTemplateExpression\main.cpp:7:34: error: invalid use of incomplete type 'class Int'
7 | typedef typename E::Type Type; //KO
| ^~~~
D:\programmation\cpp\TestTemplateExpression\main.cpp:41:7: note: declaration of 'class Int'
41 | class Int : public IntExpr
| ^~~
< /code>
Gibt es einen Trick, um dieses Problem zu lösen? Vielleicht verwenden Sie STD :: Bedingung mit Rekursion, wenn intExpr auf Leafs wahr ist, aber ich weiß nicht wie.
Mit anderen Worten, wenn ich die Situation gut verstehe: < Br />template
constexpr inline decltype(auto) operator+(IntExpr const& u, T const& v)
{
//How to scan E to get S that IntType=Int;
return IntAdd(*static_cast(&u), IntType(v));
}
Code: Select all
#include
#include
template
class IntExpr
{
public:
static constexpr bool is_leaf = false;
constexpr decltype(auto) number() const
{
return static_cast(*this).number();
}
};
template
class IntAdd : public IntExpr
{
public:
constexpr IntAdd(E1 const& u, E2 const& v) : u_(u), v_(v)
{
}
constexpr decltype(auto) number() const
{
return u_.number() + v_.number();
}
private:
typename std::conditional_t u_;
typename std::conditional_t v_;
};
template
class Int : public IntExpr
{
public:
static constexpr bool is_leaf = true;
template
constexpr Int(IntExpr const& expr)
{
number_ = expr.number();
}
template
constexpr Int(S const& number) : number_(static_cast(number))
{
}
constexpr T const& number() const
{
return number_;
}
private:
T number_{0};
};
template
constexpr inline IntAdd operator+(IntExpr const& u, IntExpr const& v)
{
return IntAdd(*static_cast(&u), *static_cast(&v));
}
template
constexpr inline decltype(auto) operator+(IntExpr const& u, T const& v)
{
return IntAdd(*static_cast(&u), Int(v));
}
template
constexpr inline decltype(auto) operator+(T const& u, IntExpr const& v)
{
return IntAdd(Int(u), *static_cast(&v));
}
int main()
{
auto const a(Int(1));
auto const b(Int(1) + 2);
auto const c((Int(1) + 2) + 3);
std::cout