考虑以下简单代码:
void g();
void foo()
{
volatile bool x = false;
if (x)
g();
}
Run Code Online (Sandbox Code Playgroud)
您可以看到,也gcc没有clang优化对的潜在调用g。在我的理解中,这是正确的:抽象机器假定volatile变量随时可能更改(由于例如被硬件映射),因此将false初始化不断折叠到if检查中将是错误的。
但是MSVC g完全消除了对的调用(保留对文件的读写volatile!)。这是符合标准的行为吗?
背景:我有时会使用这种结构来即时打开/关闭调试输出:编译器必须始终从内存中读取值,因此在调试过程中更改变量/内存应相应地修改控制流。 。MSVC输出确实重新读取了该值,但忽略了该值(可能是由于不断折叠和/或消除了死代码),这当然违背了我的意图。
编辑:
volatile这里讨论了对读写的消除:是否允许编译器优化局部volatile变量?(感谢内森!)。我认为该标准非常明确,即必须进行那些读写操作。但是,该讨论并未涵盖编译器将这些读取结果视为理所当然并基于此进行优化是否合法。我想这在标准中未指定/未指定,但是如果有人证明我做错了,我会很高兴。
我当然可以制作x一个非局部变量来避免该问题。这个问题更多是出于好奇。
考虑这个代码:
#include <vector>
#include <iostream>
enum class A
{
X, Y
};
struct Test
{
Test(const std::vector<double>&, const std::vector<int>& = {}, A = A::X)
{ std::cout << "vector overload" << std::endl; }
Test(const std::vector<double>&, int, A = A::X)
{ std::cout << "int overload" << std::endl; }
};
int main()
{
std::vector<double> v;
Test t1(v);
Test t2(v, {}, A::X);
}
Run Code Online (Sandbox Code Playgroud)
这打印:
vector overload
int overload
Run Code Online (Sandbox Code Playgroud)
为什么由于重载解析不明确而不会产生编译错误?如果删除第二个构造函数,我们会得到vector overload两次。如何/由什么指标是int一个明确更好地匹配了{}比std::vector<int>?
构造函数签名当然可以进一步修剪,但我只是被一段等效的代码所欺骗,并想确保这个问题没有丢失任何重要的东西。
我正在玩这个答案来研究它如何使用默认参数处理函数.令我惊讶的是,自由函数的结果是不同的operator():
template <typename F>
auto func(F f) -> decltype(f(42))
{
int a = 51;
return f(51);
}
template <typename F>
auto func(F f) -> decltype(f(42, 42))
{
int a = 0;
int b = 10;
return f(a, b);
}
int defaultFree(int a, int b = 0)
{
return a;
}
auto defaultLambda = [](int a, int b = 0)
{
return a;
};
int foo()
{
return func(defaultFree);
//return func(defaultLambda);
}
Run Code Online (Sandbox Code Playgroud)
上述func(defaultFree)版本在两个func …
I have a variadic template that inherits from all template arguments:
template <typename... Ts>
struct derived : Ts...
{
};
Run Code Online (Sandbox Code Playgroud)
I would also like to have a facility for expressing the type of "existing derived with added template arguments". My attempt at this is:
// Do not ODR-use (goes in namespace impl or similar)!
template<class ... NewInputs, class ... ExistingInputs>
auto addedHelper(const derived<ExistingInputs...>&)
-> derived<ExistingInputs..., NewInputs...>;
template<class ExistingInput, class ... NewInputs>
using Added = decltype(addedHelper<NewInputs...>(std::declval<ExistingInput>()));
Run Code Online (Sandbox Code Playgroud)
As a simple example, Added<derived<A, …
c++ forward-declaration language-lawyer variadic-templates c++17
上下文:令我们惊讶的是,启用 C++20 模式和两阶段合规性的 MSVC 接受以下代码:
\ntemplate<class T>\nclass X\n{\n friend int foo<X>(X x);\n\n int a = 10;\n};\n\ntemplate <class T>\nint foo(T t)\n{\n return t.a;\n}\n\nint main()\n{\n return foo(X<float>{});\n}\nRun Code Online (Sandbox Code Playgroud)\n这会编译/链接并10在 MSVC 和 gcc 中返回(但会发出 clang 声): https: //godbolt.org/z/98cd7v7a6。
那些了解两阶段查找的人会发现这看起来非常疯狂 - 我们可以在声明相应的模板之前以某种方式与模板专门化成为朋友。看起来和听起来都很不对劲。事实上,对于早期的 C++ 版本,所有编译器都会立即拒绝它: https: //godbolt.org/z/M1733EPd5
\n但 C++20 中的以下措辞似乎为此铺平了道路(或者至少使其从一开始就不是完全错误的):https://timsong-cpp.github.io/cppwp/n4861/temp .names#2.sentence-4(强调我的)
\n\n\n如果名称是一个 unqualified-id 后跟一个名称,则该名称也被视为引用模板,并且
\n<名称查找要么找到一个或多个函数,要么什么也没找到。
现在,这导致了一大堆……好吧,荒谬的极端情况。请注意,在声明之外,friend您必须以 开始模板专门化template<>,但声明中的情况并非如此friend。可以预见的是,编译器甚至无法就现在合法和不合法的内容达成一致:
| 交朋友... | 神箭 … |
|---|
在某些情况下,如果尝试实例化某些模板,则使用always_false助手来导致无条件static_assert失败:
template <class... T> struct always_false : std::false_type {};
template<class T>
struct UsingThisShouldBeAnError {
static_assert(always_false<T>::value, "You should not use this!");
};
Run Code Online (Sandbox Code Playgroud)
该帮助程序是必需的,因为模板定义必须(至少在理论上)具有至少一组模板参数,可以为其生成有效的专业化名称,以便程序格式正确:
[temp.res] / 8:如果满足以下条件,则该程序格式错误,无需进行诊断:
- 无法为模板生成有效的专业化,并且模板没有实例化,或者
[...]
(static_assert(false, "You should not use this!");因此,上面的书写格式不正确,即使没有实例化模板,编译器也总是可以触发静态断言,这不是故意的。)
这是涉及此模式的问题的快速样本(包括进一步的解释):
always_false作为标准库中的工具可能会很有用,因此我们不必不断地编写它。但是,以下问题的答案使我怀疑这是否可能:
在那里(std::enable_if_t<T>总是关于[temp.res] / 8)产生一个论点,该论点始终是void或不是一种类型,任何人对其进行进一步专门化都是非法的。因此,依赖于理论上的“ std::enable_if特殊性”的模板可避免[temp.res] / 8子句,实际上会使程序格式错误,不需要诊断。
回到我的问题:如果提供了该标准always_false,它将不得不禁止图书馆用户照常对其进行专业化(出于明显的原因)。但是,根据上述推理,这将使always_false(在理论上可以专门用于除以外的东西std::false_type)整个观点破灭-关于[temp.res] / 8,它将与std::false_type直接使用相同。
我在这个推理上错了吗?还是标准库实际上不可能以always_false有意义/有用的方式提供(无需更改核心语言)?
我定义了以下课程。
class STTreeNode
{
public:
int ind;
int parentInd;
std::vector<int> childInds;
int numTrain;
std::vector<bool> isInfluenced;
STTreeNode(int ind, int parentInd, int numTrain);
};
STTreeNode::STTreeNode(int ind, int parentInd, int numTrain) {
this->ind = ind;
this->parentInd = parentInd;
this->numTrain = numTrain;
}
Run Code Online (Sandbox Code Playgroud)
我运行了以下代码段。
STTreeNode *a = new STTreeNode(3, 4, 5);
a->childInds.push_back(20);
a->childInds.push_back(30);
a->isInfluenced.push_back(true);
a->isInfluenced.push_back(false);
for (int i = 0; i < a->childInds.size(); i++)
std::cout << &(a->childInds[i]) << " ";
std::cout << std::endl;
for (int i = 0; i < a->isInfluenced.size(); i++)
std::cout << …Run Code Online (Sandbox Code Playgroud) 这个问题让我想知道在类外成员函数定义中完全限定类名(包括全局作用域运算符)是否有用/必需。
一方面,我以前从未见过这样做(正确执行的语法似乎还不清楚)。另一方面,C ++名称查找非常简单,因此可能存在极端情况。
题:
是否曾经有过引入超出成员函数定义的定义
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
不同于
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(没有全局作用域::前缀)的情况?
请注意,成员函数定义必须放在封闭类的名称空间中,因此这不是有效的示例。
c++ qualified-name global-scope name-lookup scope-resolution-operator
我很难理解cppreference引用的有关普通默认构造函数的以下段落。我已经搜索了stackoverflow,但仍然没有一个明确的答案。所以请帮忙。
普通的默认构造函数是不执行任何操作的构造函数。与C语言兼容的所有数据类型(POD类型)都是默认可构造的。但是,与C语言不同,不能通过简单地重新解释适当对齐的存储来创建具有琐碎默认构造函数的对象,例如,使用std :: malloc分配的内存:正式引入新对象并避免潜在的未定义行为时需要placement-new。
具体来说,如果琐碎的默认构造函数什么都不做,为什么我们不能重新解释存储并假装存在具有给定类型的对象?您能否提供一些可能导致未定义行为的示例?
请考虑以下代码段:
void foo(const int&);
int bar();
int test1()
{
int x = bar();
int y = x;
foo(x);
return x - y;
}
int test2()
{
const int x = bar();
const int y = x;
foo(x);
return x - y;
}
Run Code Online (Sandbox Code Playgroud)
在我的标准的理解,既不x也没有y被允许通过改变foo在test2,而他们可以通过改变foo在test1(具有例如const_cast除去const从const int&是因为引用的对象实际上并不是常量中test1)。
现在,gcc,clang或MSVC似乎都没有优化test2到foo(bar()); return 0;,并且我可以理解,他们不希望浪费优化来传递很少在实践中应用的优化。
但是我至少对我对这种情况的理解是正确的,还是我错过了一些法律x上的修改方法test2?