静态 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.
这里有一个问题,我不太清楚其原因,但幸运的是,解决方法很简单。
考虑以下代码(让我称之为我的 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.