Undefined reference error when initializing unique_ptr with a static const

主宰稳场 提交于 2019-12-05 04:06:00

C++ has something known as the One-Definition Rule (ODR):

Informally, 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; a reference is odr-used if it is used and its referent is not known at compile time; and a function is odr-used if a function call to it is made or its address is taken. If an object, a reference or a function is odr-used, its definition must exist somewhere in the program; a violation of that is usually a link-time error.

The linked site gives the following example:

struct S {
    static const int x = 0; // static data member
    // a definition outside of class is required if it is odr-used
};
const int& f(const int& r);

int n = b ? (1, S::x) // S::x is not odr-used here
          : f(S::x);  // S::x is odr-used here: a definition is required

Your explicit constructor invocation does not "odr-use" Outside_library::my_const but the call to std::make_unique() does. When an object is odr-used it must have exactly one definition (not declaration). Your example has a declaration only. Again from cppreference:

  1. a variable x in a potentially-evaluated expression ex is odr-used unless both of the following are true:

    • applying lvalue-to-rvalue conversion to x yields a constant expression that doesn't invoke non-trivial functions
    • either x is not an object (that is, x is a reference) or, if x is an object, it is one of the potential results of a larger expression e, where that larger expression is either a discarded-value expression or has the lvalue-to-rvalue conversion applied to it

The solution as suggested by Jarod42 is to use constexpr instead of const (if you have control over the "outside library" code). If you do not, then you'll need to link the program against the library that contains the definition of Outside_library::my_const.

g++ main.cpp -std=c++14 -lOutside_library

make_unique takes (forwardind) reference of its parameter, and so odr-use it.

My_class(Outside_library::my_const) only use the value.

One solution is to define the member in a TU:

const int Outside_library::my_const;

or using constexpr value (since C++11):

class Outside_library
{
public:
    static constexpr int my_const = 100;
};

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!