Wie funktioniert ein C++-Vorlagenausdruck?
Posted: 25 Jan 2025, 17:19
Ich verwende den Vorlagenausdruck über eine benutzerdefinierte Klasse und weiß nicht, wie der Operator+ funktioniert. Das folgende Beispiel wird aus dem ursprünglichen Code vereinfacht, der darauf abzielt, meinen eigenen ganzzahligen Typ mit Expressionsvorlage zu verwenden, wobei INT -Instanzen im Ausdrucksvorlagenbaum gehalten werden. : < /p>
Der vollständige Fehler ist (da int keine Int-Instanz ist):
Um int in eine Int-Instanz zu konvertieren, habe ich versucht, eine Typedef (kommentierte Zeilen) zu verwenden, aber die Definition der Klasse ist zu diesem Zeitpunkt noch nicht vollständig.
Gibt es einen Trick, um dieses Problem zu lösen? Vielleicht die Verwendung von std::conditional mit Rekursion, wenn IntExpr auf Blättern wahr ist, aber ich weiß nicht wie.
Mit anderen Worten, wenn ich die Situation gut verstehe:
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
| ^~~
Mit anderen Worten, wenn ich die Situation gut verstehe:
Code: Select all
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>
Eine Arbeit kann darin bestehen, S -Typ (z.#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:
E1 const u_;
E2 const 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