静态 constexpr 成员似乎不同意 std::min

Static constexpr members seem not to go along with std::min

这里有一个问题,我不太清楚其原因,但幸运的是,解决方法很简单。

考虑以下代码(让我称之为我的 main.cpp):

#include <algorithm>

struct Foo {
    static constexpr float BAR = .42;

    float operator()() const noexcept {
        float zero = .0;
        return std::min(zero, BAR);
    }
};

int main() {
    Foo foo;
    foo();
}

当我尝试编译它时,出现错误:

foobar:~/Whosebug$ g++ -std=c++11 main.cpp
/tmp/ccjULTPy.o: In function 'Foo::operator()() const':
main.cpp:(.text._ZNK3FooclEv[_ZNK3FooclEv]+0x1a): undefined reference to `Foo::BAR'
collect2: error: ld returned 1 exit status

如果我使用以下语句,也会发生同样的情况(很明显):

return std::min(zero, Foo::BAR);

下面是上述示例的略微修改版本。
这个编译没有错误,即使我仍然指的是 BAR 成员:

#include <algorithm>

struct Foo {
    static constexpr float BAR = .42;

    float operator()() const noexcept {
        float zero = .0;
        float bar = BAR;
        return std::min(zero, bar);
    }
};

int main() {
    Foo foo;
    foo();
}

我没能理解为什么后一个版本编译正常而前一个版本以错误结尾。
据我所知,这两个版本都是正确的并且应该编译,但我强烈怀疑我在这里遗漏了一些重要的东西。

有什么建议吗?

这里是我的编译器版本:g++ (Debian 5.3.1-5) 5.3.1 20160101.

min选择的原型是

template<class T> 
/* constexpr since C++14 */ const T& min( const T& a, const T& b );

相关点是它通过引用获取参数,这意味着它 One-Definition-Rule (ODR) - 使用它。
而且你从未定义它,你只在你的 class 中声明它(使用初始化程序):

    static constexpr float BAR = .42;

这足以复制和以其他方式使用该值,但不能将其用作纯右值。

无需诊断违反 ODR(其更精细的点确实很细且体积庞大):

3.2 One definition rule [basic.def.odr]

4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.