在下面的示例中,我可以从lambda内部访问constexpr变量x,y而无需显式捕获它.如果x未声明为,则无法执行此操作constexpr.
是否有适用constexpr于捕获的特殊规则?
int foo(auto l) {
// OK
constexpr auto x = l();
auto y = []{return x;};
return y();
// NOK
// auto x2 = l();
// auto y2 = []{ return x2; };
// return y2();
}
auto l2 = []{return 3;};
int main() {
foo(l2);
}
Run Code Online (Sandbox Code Playgroud) 在课堂里:
class foo
{
public:
static int bar; //declaration of static data member
};
int foo::bar = 0; //definition of data member
Run Code Online (Sandbox Code Playgroud)
我们必须明确定义静态变量,否则会产生一个
undefined reference to 'foo::bar'
我的问题是:
请注意,这与先前提出的问题不重复undefined reference to static variable.这个问题打算问一下静态变量的明确定义背后的原因.
给出以下代码:
struct A { static constexpr int a[3] = {1,2,3}; };
int main () {
int a = A::a[0];
int b [A::a[1]];
}
Run Code Online (Sandbox Code Playgroud)
是A::a必然使用的ODR的int a = A::a[0]?
注意:这个问题代表了休息室辩论的一个不那么闷热/不合逻辑/无穷无尽的版本.
==>查看coliru上的完整代码段和编译.
我有一个LiteralType类填充constexpr要求:
struct MyString
{
constexpr MyString(char const* p, int s) : ptr(p), sz(s) {}
constexpr char const* data() const { return ptr; }
constexpr int size() const { return sz; }
char const *ptr = 0;
int const sz = 0;
};
Run Code Online (Sandbox Code Playgroud)
我用它作为constexpr static成员变量:
struct Foo
{
int size() { return str_.size(); }
constexpr static MyString str_{"ABC",3};
};
int main()
{
Foo foo;
return ! foo.size();
}
Run Code Online (Sandbox Code Playgroud)
但链接器说:(
Clang-3.5和GCC-4.9)
undefined …Run Code Online (Sandbox Code Playgroud) 我无法在标准中找到该程序未定义的位置:
#include <iostream>
int main()
{
int *p;
{
int n = 45;
p = &n;
}
std::cout << *p;
}
Run Code Online (Sandbox Code Playgroud)
§3.8对象生命周期中的所有情况似乎都不适用于此处.
这段代码:
void foo(int);
int main() {
const int i = 0;
auto l = [i](){foo(i);};
}
Run Code Online (Sandbox Code Playgroud)
(godbolt)
在通过clang编译时会发出编译器错误
-std=c++17 -Werror -Wunused-lambda-capture
错误消息是error: lambda capture 'i' is not required to be captured for this use.
错误是正确的:i可以在这里隐式捕获,明确捕获它是没有必要的.但是,a)警告命名不佳,因为i使用了但是警告是未使用的 lambda捕获,b)我不希望这是一个错误.我希望错误的实际未使用的lambda捕获,但不是错误的已使用显式捕获的变量,可能已被隐式捕获.
是否有铿锵设置这样做?或者我是否必须使用pragma诊断推/弹来压制错误?
在C++ 14标准§5.1.2/ 12中,它显示了一个lambda表达式的示例,该表达式显然似乎能够引用到达范围的变量x,即使:
x"这是一个例子:
void f(int, const int (&)[2] = {}) { } // #1
void test() {
const int x = 17;
auto g = [](auto a) {
f(x); // OK: calls #1, does not capture x
};
}
Run Code Online (Sandbox Code Playgroud)
看它确实编译.它似乎取决于x存在const; 如果const删除它,它不再编译因为人们期望的原因(捕获列表为空).即使我将参数设置为int不再是通用lambda,也会发生这种情况.
x即使捕获列表为空,lambda如何引用?这怎么可能同时显然没有捕获x(如评论所说)?
我在这个问题上发现的最接近的事情就是其他人在评论中切实注意到这一点.
以下是标准中的完整部分5.1.2/12:
具有关联的capture-default的lambda表达式,它不显式捕获或具有自动存储持续时间的变量(这排除了任何已发现引用init-capture的关联非静态数据成员的id-expression),如果复合语句被称为隐式捕获 …
当你进入细节时(至少对我而言),odr-used标准中的定义非常混乱.我通常依赖于"如果引用"的非正式定义,除非可以使用左值到右值转换.对于积分常数,它们应被视为rvalues,这似乎应该从参考规则中排除.这是我的示例代码无法链接:
class Test
{
public:
Test();
static constexpr int MIN_VALUE { 5 };
int m_otherValue = 10;
};
Test::Test()
{
m_otherValue = std::max(m_otherValue, MIN_VALUE);
}
int main()
{
Test t;
}
Run Code Online (Sandbox Code Playgroud)
我得到的链接器错误:
clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out /tmp/main-e2122e.o: In function `Test::Test()': main.cpp:(.text+0x2): undefined reference to `Test::MIN_VALUE' clang: error: linker command failed with exit code 1 (use -v to see invocation)
现场样本:http://coliru.stacked-crooked.com/a/4d4c27d6b7683fe8
为什么MIN_VALUE要求的定义?它只是一个字面值的常量,编译器应该优化它std::max(m_otherValue, 5).所以我只是不明白.
我想知道在函数内部定义constexpr变量时内部会发生什么.程序是否存储了被调用函数的constexpr变量的每个版本?
例:
template <class T, std::size_t M, std::size_t N>
template <std::size_t M2, std::size_t N2>
Matrix<T, M, N>::Matrix(const Matrix<T, M2, N2>& m)
{
constexpr T m_min(MATHS::min(M, M2));
constexpr T n_min(MATHS::min(N, N2));
std::size_t i(0), j(0);
for ( ; i < m_min ; ++i )
{
for ( j = 0 ; j < n_min ; ++j )
m_elts[i][j] = m.m_elts[i][j];
for ( ; j < N ; ++j )
m_elts[i][j] = MATHS::CST<T>::ZERO;
}
for ( ; i < M ; ++i ) …Run Code Online (Sandbox Code Playgroud)