c++ - g++4.7.3 和 g++4.8 的 undefined reference ?

标签 c++ c++11 compiler-errors g++ undefined-reference

考虑这段代码:

#include <iostream>
#include <array>

template <typename Type>
struct Constant
{
    constexpr Constant(const Type source) : _data({{source}}) {;}
    constexpr Constant(const std::array<Type, 1> source) : _data(source) {;}
    constexpr Constant<Type> operator()() const {return _data;}
    constexpr operator Type() const {return _data[0];}
    const std::array<Type, 1> _data;
    static constexpr Constant<Type> pi = 3.1415926535897932384626433832795028841971693993751058209749445L;
};

int main(int argc, char* argv[])
{
    std::cout<<Constant<double>::pi()<<std::endl;
    return 0;
}

我在使用 g++4.7.3g++4.8.0 时遇到编译器错误(这是对 pi 的 undefined reference >(抱歉,这是法语)):

/tmp/cctdvPfq.o: dans la fonction « main »:
main.cpp:(.text.startup+0xd): référence indéfinie vers « Constant<double>::pi »
collect2: erreur: ld a retourné 1 code d'état d'exécution

由于我的系统是全新安装的(第一次使用g++4.7.3g++4.8.0),不知道会不会出现从我的系统配置或编译器。如果来自编译器,问题出在哪里?

编辑:为什么这行得通? (没有数组的版本)

#include <iostream>
#include <array>

template <typename Type>
struct Constant
{
    constexpr Constant(const Type source) : _data(source) {;}
    constexpr Constant<Type> operator()() const {return _data;}
    constexpr operator Type() const {return _data;}
    const Type _data;
    static constexpr Constant<Type> pi = 3.1415926535897932384626433832795028841971693993751058209749445L;
};

int main(int argc, char* argv[])
{
    std::cout<<Constant<double>::pi()<<std::endl;
    return 0;
}

最佳答案

您可以避免在 pi 上调用调用运算符(operator),这样它就不会被您的程序odr-used,并且编译器可以处理 pi就像可以内联的值一样,因此不需要定义 static数据成员:

std::cout << Constant<double>::pi << std::endl;
//                             ^^

或者,您可以继续调用 pi的调用运算符,并在命名空间范围内提供静态数据成员的定义,并使用 Constant<double> 的调用运算符如您的原始代码所示:

template <typename Type>
struct Constant
{
    // ...
    static constexpr Constant<Type> pi = /* ... */;
};

template<typename Type>
constexpr Constant<Type> Constant<Type>::pi;

根据 C++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.

关于c++ - g++4.7.3 和 g++4.8 的 undefined reference ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16467802/

相关文章:

java - 包导入/编译不起作用

运行有限或无限生成器函数时出现 Python3 错误

c++ - 书错? 2002 年指向对象的指针数组

c++ - 在 Visual Studio 2005 中以 Python 获取 C++ 扩展的无痛方式

c++ - gmock中saveArg和saveArgPointee有什么区别?

c++ - 如何使用 std::conditional 选择一个自由函数

C++11 初始化列表失败 - 但仅在长度为 2 的列表上

c++ - C++ 模板能否确定正在声明/定义的实例是否为常量?

angular - ng2-completer-生产版本中产生错误

c++ - 使用显式非类型参数和隐式类型参数调用模板函数