Re: [問題] struct static const member link error

作者: carylorrk (carylorrk)   2015-01-21 12:02:06
※ 引述《shininglion (lionking - 辛巴)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Ubuntu 14.04, g++ v4.8.2
: 問題(Question):
: link error, undefined reference to XXX
: 程式碼(Code):(請善用置底文網頁, 記得排版)
: 問題程式碼如下,分在兩個檔案
: [fileA.h]
: struct A
: {
: static const int val = 0;
: };
: [fileB.cpp]
: /* something */
: std::unordered_map<int, std::string> umap;
: /* somthing */
: const std::string str = umap.at(A::val) + "123"; // error here
: 上面那行就是我的問題所在
: 因為 A::val 是 A 的 static const member,所以語法上應該是沒問題的
: compile 也確實有過,但是 link 時就噴 error 說找不到 A::val
: 後來我把 fileB.cpp 的那一段改成下面這樣就過了:
: [fileB.cpp]
: /* something */
: std::unordered_map<int, std::string> umap;
: /* something */
: const int VAL = A::val;
: const std::string str = umap.at(VAL) + "123"; // pass
: 我想不出原因為什麼一開始的寫法會 link error
: 但是改成下面這種寫法就過了
: 想請問有版友知道原因嗎?
: 謝謝!
根據標準(2003 版的 9.4.2.4)
If a static data member is of const integral or const enumeration type,
its declaration in the class definition can specify a constant-initializer
which shall be an integral constant expression (5.19). In that case,
the member can appear in integral constant expressions. The member shall
still be defined in a namespace scope if it is used in the program and the
namespace scope definition shall not contain an initializer.
所以最標準的寫法是,你應該要在 class 實作的地方(ex:fileA.cpp)加上這行
const int A::val;
至於為什麼另外 assign 到其他變數就可行而傳進 at 卻不行?
我猜是因為 static const int 有可能並沒有 allocate memory
at 接收的是一個 reference,當然會找不到。
而另外 assign 或是加上可以產生 temporary variable 的方法都可以繞過。
不過最正確的方法還是明確給他個 definition。
補上 11 標準的 9.4.2.3
If a non-volatile const static data member is of integral or enumeration
type, its declaration in the class definition can specify a
brace-or-equal-initializer in which every initializer-clause that is an
assignment-expression is a constant expression (5.19). A static data member
of literal type can be declared in the class definition with the constexpr
specifier; if so, its declaration shall specify a brace-or-equal-initializer
in which every initializer-clause that is an assignment-expression is a
constant expression. [ Note: In both these cases, the member may appear in
constant expressions. — end note ] The member shall still be defined in a
namespace scope if it is odr-used (3.2) in the program and the namespace
scope definition shall not contain an initializer.
作者: shininglion (lionking - 辛巴)   2015-01-21 16:54:00
謝謝解答,問題已確實解決. 看來以前是運氣好沒遇到

Links booklink

Contact Us: admin [ a t ] ucptt.com