Clang static 参数到 std::fill 导致链接器失败

Clang static parameter to std::fill causing linker to fail

使用 Clang++ (v3.8.0),由于 sSomeValue 是未定义的引用,以下代码无法 link。

#include <iostream>

struct MyClass
{
    static constexpr int sSomeSize = 3;
    static constexpr int sSomeValue = 10;
};

int foo()
{
    int someArray[MyClass::sSomeSize] = {};
    std::fill(std::begin(someArray), std::end(someArray), MyClass::sSomeValue);
    return someArray[0];
}

int main()
{
    std::cout << foo() << std::endl;
}

更准确地说:

clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

/tmp/main-c8de0c.o: In function `foo()':
main.cpp:(.text+0x2): undefined reference to `MyClass::sSomeValue'
/tmp/main-c8de0c.o: In function `main':
main.cpp:(.text+0x16): undefined reference to `MyClass::sSomeValue'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

但是,将 foo 的定义更改为

int foo()
{
    int someArray[MyClass::sSomeSize] = {MyClass::sSomeValue, MyClass::sSomeValue, MyClass::sSomeValue};
    return someArray[0];
}

没有表现出相同的 linker 错误,即使 sSomeValue 仍在使用。

这是怎么回事?编译器是否围绕我可能不知道的 std::fill 调用进行了一些优化? 请注意,g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out 编译、links 和输出 10 符合 v6.3.0 的预期。

错误与std::fill无关。

如果您参考下面的文档,它说:引用变量可以声明为 constexpr(它们的初始值设定项必须是引用常量表达式):

http://en.cppreference.com/w/cpp/language/constexpr

对您的代码稍加修改就可以正常工作。只需如上所述制作结构变量 "const &"。

#include <iostream>

struct MyClass
{
    static constexpr int const& sSomeSize = 3;
    static constexpr int const& sSomeValue = 10;
};

int foo()
{
    int someArray[MyClass::sSomeSize] = {};
    std::fill(std::begin(someArray), std::end(someArray), MyClass::sSomeValue);
    return someArray[0];
}

int main()
{
    std::cout << foo() << std::endl;
}

另请参阅此处,了解有关 constexprstatic 的详细解释文章 "Does static constexpr variable make sense?

特别是勾选答案的最后一段。