问题
Why does emplace_back
take a reference of the member that requires a definition? What is the difference between emplace_back(integer literal)
and emplace_back(static constexpr integer member)
?
If I switch to C++17, it compiles fine. I found that in C++17 static constexpr data members are implicitly inlined. Does it mean the compiler implicitly creates a definition for them?
Example code:
class base {
int n;
public:
base(int n):n(n) {}
};
struct base_trait {
static constexpr int n = 1;
};
int main(void) {
vector<base> v;
v.emplace_back(1); // ok
v.emplace_back(base_trait::n); // link error with -std=c++14, ok with -std=c++17
return 0;
}
回答1:
As you said, emplace_back
takes arguments by reference, so passing base_trait::n
causes it to be odr-used.
an object is odr-used if its value is read (unless it is a compile time constant) or written, its address is taken, or a reference is bound to it;
Before C++17, that means the definiton of base_trait::n
is required here. But since C++17 the behavior changed, for constexpr static data member the out-of-class definition is not needed again.
If a const
non-inline (since C++17)
static data memberor a constexpr static data member (since C++11)
is odr-used, a definition at namespace scope is still required, but it cannot have an initializer.This definition is deprecated for constexpr data members (since C++17).
A static data member may be declared inline. An inline static data member can be defined in the class definition and may specify an initializer. It does not need an out-of-class definition. (since C++17)
来源:https://stackoverflow.com/questions/50549359/emplace-back-causes-link-error-on-static-constexpr-member