Код: Выделить всё
#include
#include
template
class Expression
{};
/************************************************************************************************************************************************************/
// CRTP (Curiously Recurring Template Pattern)
template
class ExprTimes : public Expression
{
LHS lhs;
RHS rhs;
public:
// Constructor
explicit ExprTimes
(const Expression& l, const Expression& r)
: lhs(static_cast(l)),
rhs(static_cast(r)) {}
double value() const
{
return lhs.value() * rhs.value();
}
enum { numNumbers = LHS::numNumbers + RHS::numNumbers }; // The line yielding ultimately the error
std::string writeProgram(
// On input, the number of nodes processed so far
// On return the total number of nodes processed on exit
size_t& processed)
{
// Process the left sub-DAG
const std::string ls = lhs.writeProgram(processed);
const size_t ln =
- 1;
// Process the right sub-DAG
const std::string rs = rhs.writeProgram(processed);
const size_t rn = processed - 1;
// Process this node
const std::string thisString = ls + rs +
"y" + std::to_string(processed)
+ " = y" + std::to_string(ln) + " * y" + std::to_string(rn) + "\n";
++processed;
return thisString;
}
// Input: accumulated adjoint for this node or 1 if top node
void pushAdjoint(const double adjoint)
{
lhs.pushAdjoint(adjoint * rhs.value());
rhs.pushAdjoint(adjoint * lhs.value());
}
};
// Operator overload for expressions
template
inline ExprTimes operator*(
const Expression& lhs, const Expression& rhs)
{
return ExprTimes(lhs, rhs);
}
/************************************************************************************************************************************************************/
template
class ExprLog : public Expression
{
ARG arg;
public:
// Constructor
explicit ExprLog(const Expression& a)
: arg(static_cast(a)) {}
double value() const
{
return log(arg.value());
}
enum { numNumbers = ARG::numNumbers };
std::string writeProgram(
// On input, the number of nodes processed so far
// On return the total number of nodes processed on exit
size_t& processed)
{
// Process the arg sub-DAG
const std::string s = arg.writeProgram(processed);
const size_t n = processed - 1;
// Process this node
const std::string thisString = s +
"y" + std::to_string(processed)
+ " = log(y" + std::to_string(n) + ")\n";
++processed;
return thisString;
}
// Input: accumulated adjoint for this node or 1 if top node
void pushAdjoint(const double adjoint)
{
arg.pushAdjoint(adjoint / arg.value());
}
};
// Operator overload for expressions
template
inline ExprLog log(const Expression& arg)
{
return ExprLog(arg);
}
/************************************************************************************************************************************************************/
// Number type, also an expression
class Number : public Expression
{
double val;
std::shared_ptr adj; // Use a shared pointer so that copies of Number hold the same adjoint value (required to make lines 199 and 200 work)
public:
// Constructor
explicit Number(const double v) : val(v), adj(std::make_shared(0.0)) {} // code modified from text to work with shared pointer
double value() const
{
return val;
}
double adjoint() const
{
return *adj; // code modified from text to work with shared pointer
}
enum { numNumbers = 1 };
std::string writeProgram(
// On input, the number of nodes processed so far
// On return the total number of nodes processed on exit
size_t& processed)
{
const std::string thisString = "y" + std::to_string(processed) + " = " + std::to_string(val) + "\n";
++processed;
return thisString;
}
void pushAdjoint(const double adjoint)
{
*adj = adjoint; // code modified from text to work with shared pointer
}
};
/************************************************************************************************************************************************************/
auto calculate(Number t1, Number t2)
{
return t1 * log(t2); // the line triggering the error
}
/************************************************************************************************************************************************************/
template
constexpr auto countNumbersIn(const Expression&)
{
return E::numNumbers;
}
Код: Выделить всё
#include "AAD3.h"
int main()
{
Number x1(2.0), x2(3.0);
auto e = calculate(x1, x2);
double e_val = e.value();
int cnt = countNumbersIn(e);
e.pushAdjoint(1.0);
double x1_adj = x1.adjoint();
double x2_adj = x2.adjoint();
}
Компиляция приводит к следующей ошибке:
------ Build started: Project: ConsoleApplication1, Configuration: Debug x64 ------
1>In file included from C:\CODING\OTHERS\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp:1:
1>C:\CODING\OTHERS\ConsoleApplication1\ConsoleApplication1\AAD3.h(34,38): : error : invalid arithmetic between different enumeration types ('Number::(unnamed enum at ./AAD3.h:151:2)' and 'ExprLog::(unnamed enum at ./AAD3.h:94:2)')
1> 34 | enum { numNumbers = LHS::numNumbers + RHS::numNumbers };
1> | ~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~
[/code]
он хорошо компилирует с теми компиляторами Intel только тогда, когда Language Standard C ++ равен iso c ++ 20 стандарт (/std: c ++ 20) или ниже.
Я попытался наивенно отменить оба элемента последней строки, чтобы без успеха. Я не вижу, как исправить код, чтобы избавиться от этой ошибки, когда я использую компилятор Intel. (Только с компилятором Intel, а не с Microsoft.)>
Подробнее здесь: https://stackoverflow.com/questions/796 ... -different
Мобильная версия