【问题标题】:Static constexpr members seem not to go along with std::min [duplicate]静态 constexpr 成员似乎不与 std::min [重复]
【发布时间】:2016-04-10 20:09:28
【问题描述】:

这是一个问题,其原因对我来说很模糊,但幸运的是,解决方法很简单。

考虑以下代码(让我称之为我的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:~/stackoverflow$ g++ -std=c++11 main.cpp
/tmp/ccjULTPy.o:在函数“Foo::operator()() const”中:
main.cpp:(.text._ZNK3FooclEv[_ZNK3FooclEv]+0x1a): 未定义对 `Foo::BAR' 的引用
collect2:错误:ld 返回 1 个退出状态

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

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

【问题讨论】:

  • std::min,通过引用取参数,ODR-使用静态成员,需要对应定义
  • 有趣,三个 cmets,三种不同的方法。 Nathan,它不是我使用的编译器,反正很有趣。 Piotr,从你的角度来看,我没有完全理解这个问题,你能更详细一点吗? R.Sahu:浮点问题?实际上,在处理浮点变量时,我在实际代码中也遇到了错误......
  • @skypjack 你只声明了一个静态 constexpr 成员,你没有定义它。但是,要将它传递给std::min,它必须有一个地址(因为它是通过引用获取的)。如果您只将其值分配给局部变量,那么它是一个左值到右值的转换,它不使用 ODR-使用静态数据成员,因此它可以工作

标签: c++ c++11 static constexpr stl-algorithm


【解决方案1】:

min 选择的原型是

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

相关的一点是它通过引用获取参数,这意味着它使用单一定义规则 (ODR)。
而且你从来没有定义它,你只是在你的类中声明它(使用初始化器):

    static constexpr float BAR = .42;

这对于复制和以其他方式使用该值来说已经足够了,但对于将其用作除纯右值之外的任何东西来说是不够的。

Why does constexpr static member (of type class) require a definition?

无需诊断是否违反了 ODR(其更精细的点确实很好且数量庞大):

3.2 一定义规则[basic.def.odr]

4 每个程序都应包含一个对每个非内联函数或 odr 使用的变量的定义 在该计划中;无需诊断。定义可以显式出现在程序中,可以查到 在标准库或用户定义库中,或(在适当时)隐式定义(参见 12.1、12.4 和 12.8)。内联函数应在使用它的每个翻译单元中定义。

【讨论】:

    猜你喜欢
    • 2016-12-05
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2015-02-25
    相关资源
    最近更新 更多