请考虑以下代码:
#include <iostream>
template<typename T>
void inc1(T&& x)
{
T y = x;
++y;
}
template<typename T>
void inc2(T& x)
{
T y = x;
++y;
}
int main()
{
int a = 10;
inc1(a); // a is now 11
int b = 10;
inc2(b); // b remains 10
}
Run Code Online (Sandbox Code Playgroud)
替换后我们有
void inc1(int& x)
{
int& y = x; // reference to x
++y; // increments x
}
void inc2(int& x)
{
int y = x; // copy of x …Run Code Online (Sandbox Code Playgroud) 简而言之:
如何编写测试,检查我的类是不可复制的还是可复制的,但只能移动并可移动分配?
一般来说:
如何编写测试,确保特定代码不编译?像这样:
// Movable, but non-copyable class
struct A
{
A(const A&) = delete;
A(A&&) {}
};
void DoCopy()
{
A a1;
A a2 = a1;
}
void DoMove()
{
A a1;
A a2 = std::move(a1);
}
void main()
{
// How to define these checks?
if (COMPILES(DoMove)) std::cout << "Passed" << std::endl;
if (DOES_NOT_COMPILE(DoCopy)) std::cout << "Passed" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我想与SFINAE有关,但有一些现成的解决方案,也许是在提升?
C ++中的常量表达式具有非常整洁的特性:它们的求值不能具有未定义的行为(7.7.4.7):
表达式e是核心常量表达式,除非按照抽象机([intro.execution])的规则对e求值,将求出以下值之一:
...
一种操作,其操作将具有本文档的[引言] [cpp]中指定的不确定的行为[注意:例如,包括带符号整数溢出([expr.prop]),某些指针算术([expr.add],除以零或某些移位操作-尾注];
尝试将13!in 的值存储在constexpr int确实产生一个不错的编译错误:
constexpr int f(int n)
{
int r = n--;
for (; n > 1; --n) r *= n;
return r;
}
int main()
{
constexpr int x = f(13);
return x;
}
Run Code Online (Sandbox Code Playgroud)
输出:
9:19: error: constexpr variable 'x' must be initialized by a constant expression
constexpr int x = f(13);
^ ~~~~~
4:26: note: value 3113510400 is outside the range of representable values …Run Code Online (Sandbox Code Playgroud) 我需要使用显示器作为我的特殊应用程序的"私人"设备,我想将它用作一种类型的手电筒并在其上全屏绘制特殊图案.我不希望OS(Windows 7)将此监视器识别为常用监视器.即用户不应该将鼠标移动到该监视器,或更改其分辨率,或在其上运行屏幕保护程序或其他任何内容.但我希望能够从我的应用程序中与它进行交互.使用HDMI电缆将显示器插入视频卡(最可能是nVidia).
最简单的方法是什么?所有解决方案都受到赞赏,包括购买额外的适配器或简单的视频卡,或任何其他特殊设备.我现在想象的唯一解决方案是将显示器插入另一台计算机,在该计算机上运行一个守护程序,通过以太网或其他任何方式将其连接到我的计算机,从我的计算机与该守护程序进行通信.它很丑陋,需要额外的电脑.但我需要解决这个问题.
在我们的代码库中,我们有许多这样的结构:
auto* pObj = getObjectThatMayVeryRarelyBeNull();
if (!pObj) throw std::runtime_error("Ooops!");
// Use pObj->(...)
Run Code Online (Sandbox Code Playgroud)
在99.99%的情况下,不会触发此检查.我正在考虑以下解决方案:
auto& obj = deref_or_throw(getObjectThatMayVeryRarelyBeNull());
// Use obj.(...)
Run Code Online (Sandbox Code Playgroud)
凡deref_or_throw声明如下:
template<class T> T& deref_or_throw(T* p) {
if (p == nullptr) { throw std::invalid_argument("Argument is null!"); }
return *p;
}
Run Code Online (Sandbox Code Playgroud)
该代码更清晰,可以根据需要使用.
问题是:我是否重新发明轮子?在标准或提升中是否有一些相关的解决方案?或者你对解决方案有一些评论?
PS.相关问题(没有令人满意的答案):是否存在与NullPointerException相当的C++
问题很简单。是否可以构造这样一个类型 T,对于它下面的两个变量声明会产生不同的结果?
T t1 = {};
T t2{};
Run Code Online (Sandbox Code Playgroud)
我已经研究 cppreference 和标准一个多小时了,我了解以下内容:
T t2{};是一个值初始化。这里没有惊喜。T t1 = {}是一个带有空括号初始化列表的列表初始化。但是最后一个很棘手,因为“列表初始化的效果”是一个令人印象深刻的......列表。对于类,基本类型和聚合似乎归结为值初始化。但我不确定我没有错过任何东西。
也许您可以提供一个上下文,其中两个声明会产生不同的效果?
UPD:关于explicit构造函数的优秀答案!下一级:是否有可能两个语句都编译,但对编译/运行时有不同的影响?
看一下这两个重载的函数模板:
template <class T>
int foo(T& x) { // #1
return 1;
}
template <class T>
int foo(T&& x) { // #2
return 2;
}
Run Code Online (Sandbox Code Playgroud)
我foo通过以下方式调用:
int i;
foo(i); // calls #1
Run Code Online (Sandbox Code Playgroud)
并且明确选择了重载#1:https ://gcc.godbolt.org/z/zchK1zxMW
这似乎是一个正确的行为,但我无法理解为什么会发生(而且我实际上有代码,这不是我所期望的)。
从过载分辨率:
如果任何候选者是函数模板,则其特化是使用模板参数推导生成的,并且此类特化被视为与非模板函数一样,除非在决胜规则中另有指定。
好的,让我们生成专业化。对于#1来说,这很容易,它就变成了int foo(int& x)。对于 #2,适用特殊扣除规则,因为它是转发参考。i是一个左值,因此T被推导为int&并T&&变为int& &&,在引用折叠后变为 just int&,产生结果int foo(int& x)。这与#1 完全相同!
所以我希望看到一个不明确的调用,但这并没有发生。谁能解释一下为什么吗?这里使用什么决定因素来选择最佳可行的功能?
另请参阅Slack 中的相关讨论,其中有一些想法。
以下是代码审查中发现的任务.我想根据特殊类型的比较谓词从集合中选择最小值.像这样:
struct Complex { ... };
float calcReduction(Complex elem);
Complex findMinValueWithPredicates(const std::vector<Complex>& values)
{
auto it = std::min_element(values.begin(), values.end(),
[](const Complex& a, const Complex& b) {
return calcReduction(a) < calcReduction(b);
});
if (it == values.end()) throw std::runtime_error("");
return *it;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我找到了基于谓词的最小元素.此谓词计算两个值的减少,float然后比较这些浮点数.工作正常,看起来整洁.
你能看到问题吗?是的,对于一组N元素calcReduction()称为2N时间,而它只足以计算它N- 每个元素一次.
解决此问题的一种方法是编写显式计算:
Complex findMinValueExplicit(const std::vector<Complex>& values)
{
float minReduction = std::numeric_limits<float>::max();
Complex minValue;
for (Complex value : values)
{
float reduction = calcReduction(value);
if (reduction < …Run Code Online (Sandbox Code Playgroud) 在关于概念N3701的最新论文中,该sort算法有以下示例:
template<typename Cont>
requires Sortable<Cont>()
void sort(Cont& cont)
Run Code Online (Sandbox Code Playgroud)
其中Sortable概念被定义为
template<typename T>
concept bool Sortable()
{
return Permutable_container<T>() && Totally_ordered<Value_type<T>>();
}
Run Code Online (Sandbox Code Playgroud)
其中Totally_ordered,毫不奇怪,定义为
template<typename T>
constexpr bool Totally_ordered()
{
return Weakly_ordered<T>() && Equality_comparable<T>();
}
Run Code Online (Sandbox Code Playgroud)
反过来Equality_comparable被定义为
template<typename T>
constexpr bool Equality_comparable()
{
return requires(T a, T b) {
{a == b} -> bool;
{a != b} -> bool;
};
}
Run Code Online (Sandbox Code Playgroud)
我没有找到定义Weakly_ordered,但我相信它应该是这样的(我是对的吗?)
template<typename T>
constexpr bool Weakly_ordered()
{
return requires(T …Run Code Online (Sandbox Code Playgroud) 这听起来像一个基本问题,但我没有找到任何全面的答案,所以在这里.请考虑以下代码段:
struct A {
const std::string& s;
A(const std::string& s) : s(s) {}
};
int main() {
A a("abc");
std::cout << a.s << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
演示.
只要我明白,这就是UB.字符串文字"abc"绑定到const std::string&构造函数中,创建一个临时字符串对象.它也必须引用a.s,并且一旦a被构造就被销毁.也就是说,const引用不能链延长寿命延长.晃来晃去参考,热潮.在这个特殊情况下,我在ideone.com上看不到任何输出,但任何事情都可能发生(请记住速龙).
好的,这个很清楚.但是,如果这实际上是我们的意图呢:我们想要存储对象的const引用?对现有的,不是暂时的?这听起来像是一项非常自然的任务,但我只想出一个(几乎)自然的解决方案.接受构造函数的参数std::reference_wrapper而不是引用:
A(std::reference_wrapper<const std::string> r) : s(r) {}
Run Code Online (Sandbox Code Playgroud)
既然std::reference_wrapper删除了临时的构造函数:
reference_wrapper( T&& x ) = delete;
Run Code Online (Sandbox Code Playgroud)
这个工作就像预期一样.但是,这并不是很优雅.我能想到的另一种方法是接受转发引用T&&并拒绝除const l-value字符串之外的所有内容std::enable_if.我认为这更不优雅.
还有其他方法吗?
UPD另一个问题:这是合法使用std::reference_wrapper,还是可能被认为过于具体?