#include <iostream>
class Account {
public:
static double GetCircumference(const double &dR) { return 2 * dR * 3.1415926; }
static constexpr double cd = 3.0;
};
// constexpr double Account::cd;
int main()
{
std::cout << Account::GetCircumference(Account::cd) << std::endl;
}
The code is wrong unless I remove the "//". But if I only change (const double &dR) to (const double dR), it becomes ok too. Why?
CodePudding user response:
In C 11, this in-class declaration:
static constexpr double cd = 3.0;
is not a definition (... until C 17; after which constexpr
static data members are implicitly inline).
This is a out-of-class definition:
constexpr double Account::cd;
A definition is is needed if Account::cd
is odr-used, which it is if it is passed to:
double GetCircumference(const double &dR);
as its reference is taken.
[basic.def.odr]/3 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. [...]
However, if it is passed to
double GetCircumference(const double dR);
it is not odr-used:
[basic.def.odr]/2 An expression is potentially evaluated unless it is an unevaluated operand (Clause [expr]) or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression ([expr.const]) and the lvalue-to-rvalue conversion ([conv.lval]) is immediately applied.
and a definition is not required.