为什么我允许std::move在包含具有已删除移动语义的类型的字段的类上使用(情况1),但是不允许在这样的类的实例上使用它(情况2)?
我理解案例2.我已经明确删除了移动构造函数,所以如果我试图移动它,我会收到错误.但我希望在案例1中也会出现这种情况,这样的类也在被移动.
class TestNonMovable {
std::string ss;
public:
TestNonMovable(){}
TestNonMovable(const TestNonMovable&) {}
TestNonMovable(TestNonMovable&&) = delete;
};
class SomeClass {
TestNonMovable tnm;
};
int main() {
// case1: This compiles, my understanding is that for SomeClass::tnm compiler will use copy constrctor
SomeClass sc1;
SomeClass sc2 = std::move(sc1);
// case2: This does not compile, move constructor is explicitly deleted, compiler will not try using copy constructor
TestNonMovable tnm;
TestNonMovable tnm2 = std::move(tnm); //error: use of deleted function 'TestNonMovable::TestNonMovable(TestNonMovable&&)'
}
Run Code Online (Sandbox Code Playgroud) 我们有,uniform_int_distribution并且uniform_real_distribution不可能有一个包含uniform_distribution,专门用于float/double和int/...,当指定时?
我有一个功能:
void foo(int n) {
std::cout << "foo(int)\n";
}
Run Code Online (Sandbox Code Playgroud)
可以使用不同的参数调用,它可以是char,double,float等:
foo(123); // 1
foo('c'); // 2
foo(0.2); // 3
foo(0.2f); // 4
// ...
Run Code Online (Sandbox Code Playgroud)
...但我想只允许int参数(字面值或变量),以便2,3,4,......以上是非法的.我目前的解决方案是删除那些重载:
void foo(char) = delete;
void foo(float) = delete;
void foo(double) = delete;
Run Code Online (Sandbox Code Playgroud)
但是这个重载列表可能真的很长,总是有人可以编写一个类,它会隐式转换为int允许以int错误方式使用我唯一函数的类,所以我发现写(而不是长显式列表):
template<typename T>
void foo(T) = delete;
Run Code Online (Sandbox Code Playgroud)
按预期工作.
上面使用模板有什么缺点吗?或者有更好的方法来解决这个问题?
为什么要向前宣布如下:
template<typename T> struct std::hash;
Run Code Online (Sandbox Code Playgroud)
无法使用gcc和clang进行编译,但是使用Visual Studio 2015进行编译?
gcc 6.1.0(使用coliru):
main.cpp:11:34: error: invalid use of template-name 'std::hash' without an argument list
template<typename T> struct std::hash;
^~~~
Run Code Online (Sandbox Code Playgroud)
clang 3.8.0(使用coliru):
main.cpp:11:29: error: forward declaration of struct cannot have a nested name specifier
template<typename T> struct std::hash;
^~~~~
Run Code Online (Sandbox Code Playgroud)
它在VS(http://webcompiler.cloudapp.net/)下工作.哪个编译器是对的?
顺便说一句.C++ Primer第5版中使用了相同的声明.好吧 - 几乎一样,它使用class而不是struct:template <class T> class std::hash;这是错误的.
完整代码:
#include <unordered_map>
/*
// compiles with gcc,clang,VS
namespace std {
template<typename T>
struct hash;
}*/
// Compiles …Run Code Online (Sandbox Code Playgroud) 我检查了gcc和clang,两者都没有生成任何警告.我想从foo()临时的生命周期将延长,直到完整表达式结束,这是bar函数调用中的分号所在.
#include <iostream>
#include <string>
struct A
{
std::string foo() const{ return "aaa"; }
};
void bar(const char* c) {
std::cout << c;
}
int main()
{
A a;
bar(a.foo().c_str()); // Is this safe?
bar(a.foo().substr().c_str()); // or this
}
Run Code Online (Sandbox Code Playgroud) 我有以下模板功能:
template<typename T> void foo2(T t) {}
Run Code Online (Sandbox Code Playgroud)
我知道我不能用它来调用它:
foo2({1,2,3});
Run Code Online (Sandbox Code Playgroud)
因为初始化列表是模板参数的非推导上下文.我必须使用:
foo2<std::initializer_list<int>>({1,2,3});
Run Code Online (Sandbox Code Playgroud)
但我也可以用:
foo2(std::initializer_list<int>({1,2,3}));
Run Code Online (Sandbox Code Playgroud)
这让我想知道有什么区别:{1,2,3}和std::initializer_list<int>({1,2,3})?
在"C++编程语言"第四版 - 第23.4.7章"朋友"中,我找到了以下示例(我稍微修改了它以仅显示相关部分):
template<typename T>
class Vector {
public:
friend Vector operator*<>(const Vector& v, int f);
^^ ~~~~ ?
};
template<typename T>
Vector<T> operator*(const Vector<T>& v, int f) {
return v;
}
Run Code Online (Sandbox Code Playgroud)
我试图编译它,但我得到以下错误(clang):
main.cpp:8:20: error: friends can only be classes or functions
friend Vector operator*<>(const Vector& v, int f);
^
main.cpp:8:29: error: expected ';' at end of declaration list
friend Vector operator*<>(const Vector& v, int f);
^
;
2 errors generated.
Run Code Online (Sandbox Code Playgroud)
书解释说:
需要友元函数名称后面的<>来表明朋友是模板函数.如果没有<>,则假定为非模板函数.
这就是全部.
如果没有<>此代码编译,但在使用operator*时(例如Vector<int> v; v*12; …
以下代码:
std::optional<std::string> so;
std::cout << so->size() << std::endl;
std::cout << so.has_value();
Run Code Online (Sandbox Code Playgroud)
输出:
0
0
Run Code Online (Sandbox Code Playgroud)
我的问题是so->size()在空的可选项上调用 : 是否安全。我使用了 clang 消毒剂,但它没有在上面的代码中报告任何 UB。
我正在阅读有关泛型的内容,并且了解到它们不允许使用instanceof. 但是,以下代码可以编译:
WeakReference<String> ps = new WeakReference<>(new String());
if (ps instanceof WeakReference<String>) {
System.out.println("Ok");
}
Run Code Online (Sandbox Code Playgroud)
谁能澄清我不明白的事情吗?
对此的机制进行了很好的解释:模板“复制构造函数”不会阻止编译器生成的move构造函数,但我想更好地理解为什么这样做。我知道即使程序员编写了任何其他构造函数,也不会生成move构造函数,因为这表明对象的构造很简单,并且自动生成的构造函数可能是错误的。那么,为什么具有与副本构造函数相同签名的模板化构造函数不能简单地命名为副本构造函数呢?
例:
class Person {
public:
template<typename T>
Person(T&& t) : s(std::forward<T>(t)) {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
Person(int n) {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
// No need to declare copy/move constructors as compiler will do this implicitly
// Templated constructor does not inhibit it.
//Person(const Person&) = default;
//Person(Person&&) = default;
private:
std::string s;
};
Run Code Online (Sandbox Code Playgroud)
然后:
Person p("asd"); // OK!
//Person p4(p); // error as Person(T&&) is a better match
Run Code Online (Sandbox Code Playgroud)
如果我做pconst:
const …Run Code Online (Sandbox Code Playgroud) 是否可以向所有类添加扩展功能?我正在考虑将其添加到一些常见的基类(如Object)中。可能吗?
在下面的代码中,我没有指定任何捕获模式,但some_static在闭包内是可见的.所以问题是它是否实际被捕获,或者以某种方式以其他方式引用.
额外的问题是是否允许编译器将这样的lambda转换为自由函数而不是闭包 - 这可能是因为没有指定捕获列表.
std::vector<std::function<bool(int)>> filters;
int main()
{
static int some_static = 1;
filters.emplace_back([](int){
return some_static == 2;
});
}
Run Code Online (Sandbox Code Playgroud) 我只想打印匹配的行并删除不匹配的行,但具有以下内容:
$ echo test12 test | sed -n 's/^.*12/**/p'
Run Code Online (Sandbox Code Playgroud)
我总是得到:
** test
Run Code Online (Sandbox Code Playgroud)
代替:
**
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
[编辑1]
我提供了更多我需要的信息——实际上我应该从它开始。因此,我有一个命令产生大量输出行,我只想抓取部分行 - 匹配的行,并剥离结果。因此,在上面的示例中,12 是为了查找该行的匹配部分的结尾,而不是 ** 我应该放置 & 来表示匹配的字符串。所以完整的例子是:
echo test12 test | sed -n 's/^.*12/&/p'
Run Code Online (Sandbox Code Playgroud)
它产生与输入完全相同的输出:
test12 test
Run Code Online (Sandbox Code Playgroud)
预期输出是:
test12
Run Code Online (Sandbox Code Playgroud)
按照建议,我开始寻找 grep 替代方案,以下内容看起来很有希望:
$ echo test12 test | grep -Eo "^.*12"
Run Code Online (Sandbox Code Playgroud)
但我不知道如何格式化匹配的部分,这只会删除不匹配的文本。