这只是出现在另一个问题的背景下.
显然,类模板中的成员函数只有在使用ODR时才会被实例化.有人可以解释一下究竟是什么意思.关于单一定义规则(ODR)的维基百科文章未提及" ODR使用 ".
但是标准将其定义为
名称显示为潜在评估表达式的变量是odr-used,除非它是满足出现在常量表达式(5.19)中的要求的对象,并且立即应用左值到右值转换(4.1).
在[basic.def.odr]中.
编辑:显然这是错误的部分,整个段落包含不同事物的多个定义.这可能是类模板成员函数的相关内容:
一个非重载函数,其名称显示为可能已评估的表达式或一组候选函数的成员,如果从可能已评估的表达式引用时通过重载决策选择,则使用该函数,除非它是纯虚拟的函数及其名称未明确限定.
但我不明白,这个规则如何在多个编译单元中工作?如果我显式实例化一个类模板,是否所有成员函数都被实例化了?
C++ 14草案(N3936)在§3.2/ 3中陈述:
变量x的名称显示为潜在评估的表达式ex,除非将lvalue-to-rvalue转换(4.1)应用于x,否则将生成不调用任何非平凡函数的常量表达式(5.19),并且如果x是一个对象,ex是表达式e的潜在结果集合的元素,其中左值到右值的转换(4.1)应用于e,或者e是丢弃值表达式(第5节).
这对我没有任何意义:如果表达式e是丢弃值表达式取决于使用的上下文e.表达式语句(第6.2节)中使用的每个表达式都是一个丢弃值表达式.如果左值到右值转换被施加到e还依赖于上下文e中被使用.
而且,表达式在另一个表达式的潜在结果集合中意味着什么.人们需要表达式相等的概念才能确定集合的成员资格.但我们没有参考透明度,所以我看不出如何实现这一点.
为什么从C++ 11改为C++ 14?这怎么解释?就目前而言,它没有意义.
不幸的是,我有点困惑constexpr,在头文件中声明的全局常量和odr.
简而言之:我们可以从这里结束
https://isocpp.org/files/papers/n4147.pdf
那
constexpr MyClass const MyClassObj () { return MyClass {}; }
constexpr char const * Hello () { return "Hello"; }
Run Code Online (Sandbox Code Playgroud)
比...好
constexpr MyClass const kMyClassObj = MyClass {};
constexpr char const * kHello = "Hello";
Run Code Online (Sandbox Code Playgroud)
如果我想"只使用"那些全局声明/定义的实体并且不想考虑我如何使用它们,那么在头文件中定义全局变量?
这是对未定义的静态constexpr char [] []的引用的后续问题.
以下程序构建并运行良好.
#include <iostream>
struct A {
constexpr static char dict[] = "test";
void print() {
std::cout << A::dict[0] << std::endl;
}
};
int main() {
A a;
a.print();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我A::print()改为:
void print() {
std::cout << A::dict << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我在g ++ 4.8.2中收到以下链接器错误.
/tmp/cczmF84A.o: In function `A::print()': socc.cc:(.text._ZN1A5printEv[_ZN1A5printEv]+0xd): undefined reference to `A::dict' collect2: error: ld returned 1 exit status
可以通过添加一行来解决链接器错误:
constexpr char A::dict[];
Run Code Online (Sandbox Code Playgroud)
在课堂定义之外.
但是,我不清楚为什么使用数组的一个成员在使用数组时不会导致链接器错误导致链接器错误.
为什么下面的工作原理gcc却没有clang,(现场观看):
constexpr int giveMeValue() { return 42; }
struct TryMe {
static constexpr int arr[1] = {
giveMeValue()
};
};
int main() {
int val = TryMe::arr[0];
return val;
}
Run Code Online (Sandbox Code Playgroud)
我得到一个未解决的外部符号与clang.
是TryMe::arr[0]一个对象?如果是的话,它是否经常使用?
在下面的...
struct C {};
constexpr C c;
void g(C);
template<typename T>
void f(T&& t) {
g(std::forward<T>(t));
}
int main() {
f(c);
}
Run Code Online (Sandbox Code Playgroud)
是否使用了codr?为什么/为什么不呢?
我很难理解这段代码(C++ 14草案标准[conv.lval]中的一个例子)是如何调用未定义的行为的g(false).为什么constexpr让程序有效?
另外,"不访问y.n" 是什么意思?在两个调用中g()我们都返回n数据成员,为什么最后一行说它不访问它?
struct S { int n; };
auto f() {
S x { 1 };
constexpr S y { 2 };
return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false); // undefined behavior due to access of x.n outside its
// lifetime
int n = g(true); // OK, does not access y.n
Run Code Online (Sandbox Code Playgroud)