struct A {
A(int) {}
};
struct B {
B(A) {}
};
int main() {
B b({0});
}
Run Code Online (Sandbox Code Playgroud)
构造出现b以下错误:
In function 'int main()':
24:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
24:9: note: candidates are:
11:2: note: B::B(A)
10:8: note: constexpr B::B(const B&)
10:8: note: constexpr B::B(B&&)
Run Code Online (Sandbox Code Playgroud)
我期待B::B(A)被召唤,为什么在这种情况下它是模棱两可的?
考虑以下关于路径分解的断言,其中每个局部变量例如stem具有明显的初始化,例如auto stem = path.stem()-
assert(root_path == root_name / root_directory);
assert(path == root_name / root_directory / relative_path);
assert(path == root_path / relative_path);
assert(path == parent_path / filename);
assert(filename == stem + extension);
Run Code Online (Sandbox Code Playgroud)
这一切都有效,除了最后一行 - 因为fs::path没有定义operator+.它有operator+=,但没有operator+.
这是什么故事?
我已经确定我可以通过添加自己的代码来编译代码operator+.有什么理由不这样做吗?(请注意,这是在我自己的命名空间中;我没有重新打开namespace std.)
fs::path operator+(fs::path a, const fs::path& b)
{
a += b;
return a;
}
Run Code Online (Sandbox Code Playgroud)
我对这个问题的唯一假设是:
也许设计师担心operator+会太容易混淆使用std::string的operator+.但这看起来很愚蠢,因为它在语义上完全相同(所以为什么要关心它是否会混淆?).而这也似乎设计师不关心新手的困惑,当他们设计path.append("x")做一些语义不同的str.append("x")和 …
我有以下代码不能在Visual C++ 2015下编译,但在GCC 4.8.4下编译.我想知道哪个是对的?有问题的代码如下:
template <class T> class ATemplate;
template <class R, class A1>
struct ATemplate<R(A1)>{ };
int main()
{
ATemplate<void(int)> x;
// ATemplate<void(int)override> y; //---Does not compile!!!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在下面(或const)使用override作为说明符是错误的.GMock库中存在类似的代码,其中宏扩展用于生成模板参数(包括覆盖)以及实际的函数签名.
删除注释掉的行时,Visual C++ 2015会产生以下错误:
x.cpp(11): error C2062: type 'int' unexpected
x.cpp(11): error C2976: 'ATemplate': too few template arguments
x.cpp(4): note: see declaration of 'ATemplate'
x.cpp(11): error C2079: 'y' uses undefined class 'ATemplate'
Run Code Online (Sandbox Code Playgroud)
下面的答案之一提到覆盖在自由函数的上下文中是没有意义的(有效点) - 这是否意味着GCC在这里是错误的.在这种情况下,const说明符也没有意义(对于自由函数),但仍允许(通过VC++)??? 此外,它提到虚拟说明符应仅存在于声明中 - 这与此情况没有区别(因为不存在定义).对于virtual关键字,可以在派生中省略,因为它对代码是否编译没有区别,但对于覆盖情况,它不是好的,因为它会产生很大的不同.
当使用ReturnType(ArgType arg)...可能的const或override说明符作为宏参数(如GMock那样)时,VCC施加的限制导致此代码无法编译(显然也是Clang的情况).哪个是对的?
标准没有说明在这种情况下(模板参数的上下文?)不应该使用覆盖说明符,是吗?
以下代码成功编译了大多数现代C++ 11兼容编译器(GCC> = 5.x,Clang,ICC,MSVC).
#include <string>
struct A
{
explicit A(const char *) {}
A(std::string) {}
};
struct B
{
B(A) {}
B(B &) = delete;
};
int main( void )
{
B b1({{{"test"}}});
}
Run Code Online (Sandbox Code Playgroud)
但是为什么它首先编译,以及列出的编译器如何解释该代码?
为什么MSVC能够在没有的情况下编译它B(B &) = delete;,但其他3个编译器都需要它?
为什么在删除复制构造函数的不同签名时,除了MSVC之外的所有编译器都会失败,例如B(const B &) = delete;?
编译器甚至都选择相同的构造函数吗?
为什么Clang会发出以下警告?
17 : <source>:17:16: warning: braces around scalar initializer [-Wbraced-scalar-init]
B b1({{{"test"}}});
Run Code Online (Sandbox Code Playgroud) AFAIK非可变lambda捕获变量为const.这让我想知道他们为什么还能被感动?
auto p = std::make_unique<int>(0);
auto f = [p = std::move(p)](){ p->reset(); }; // Error, p is const
auto f2 = std::move(f); // OK, the pointer stored inside lambda is moved
Run Code Online (Sandbox Code Playgroud) 我有以下代码:
template <class T>
class lit {
public:
lit(T l) : val(l) {}
T val;
};
template <class T>
class cat {
public:
cat(lit<T> const& a, lit<T> const& b) : a(a), b(b) {}
lit<T> const& a;
lit<T> const& b;
};
template <class T>
cat<T> operator+(lit<T> const& a, lit<T> const& b) {
return cat(a, b);
}
int main() {
auto r1 = cat((lit ('b')), lit('d')); // compiles
auto r2 = (lit ('b')) + lit('d') ; // doesn't compile
auto r3 = …Run Code Online (Sandbox Code Playgroud) c++ templates class-template template-argument-deduction c++17
令我感到惊讶的是,在下面的示例中,声明Middle的基类private使该名称在后续派生中不可用作为类型.
class Base {
public:
Base(Base const& b) : i(b.i) {}
int i;
};
class Middle : private Base { //<<<<<<<<<<<
public:
Middle(Base const* p) : Base(*p) {}
};
class Upper : public Middle {
public:
Upper(Base const* p) : Middle(p) {} //<<<<<<<<<<<
};
Run Code Online (Sandbox Code Playgroud)
用g ++编译(Debian 6.3.0-18 + deb9u1)6.3.0 20170516 ......
g++ -std=c++11 privateBase.cpp
Run Code Online (Sandbox Code Playgroud)
我得到以下诊断:
privateBase.cpp:15:9: error: ‘class Base Base::Base’ is inaccessible within this context
Upper(Base const* p) : Middle(p) {}
^~~~
privateBase.cpp:1:12: note: declared here
class Base {
^ …Run Code Online (Sandbox Code Playgroud) 在C11和C++ 11 1中是否有以下定义的行为?
bool has4() {
char buf[10] = {0, 1, 2, 4};
return memchr(buf, 4, 20);
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们通过了太长的时间memchr.数组有10个元素,但是我们传递了20.但是,我们要搜索的元素总是在结束之前找到.我很清楚这是否合法.
如果允许这样做,则会限制实现的灵活性,因为实现不能依赖于大小是可访问存储器区域大小的有效指示,因此必须小心读取超出找到的元素.一个例子是一个想要从传入指针开始执行16字节SIMD加载然后并行检查所有16个字节的实现.如果用户传递的长度为16,则只有在需要访问整个长度时才会安全.
否则(如果上面的代码是合法的),实现必须避免对目标元素之外的元素进行潜在的错误处理,例如通过对齐加载(可能很昂贵)或检查指针是否接近保护边界的末尾.
1这里是一个罕见的问题,我猜C和C++的标记是有效的:据我所知,C++标准只是在行为方面通过引用直接推迟到C标准,但如果不是这样的话我想知道.
请考虑以下代码:
class StringTokenizer
{
private:
char m_delimiter;
std::istringstream m_string;
public:
explicit StringTokenizer(const std::string& str, char delimiter)
: m_string(str)
, m_delimiter(delimiter)
{
}
template <class Container>
operator Container ()
{
Container container;
for (std::string token; std::getline(m_string, token, m_delimiter); )
{
container.insert(container.end(), token);
}
return container;
}
};
Run Code Online (Sandbox Code Playgroud)
这是用法:
vector<string> tmp = StringTokenizer("123 456", ' '); //Please note the implicit conversion
Run Code Online (Sandbox Code Playgroud)
调试时发生以下情况(使用VS2013):
在return转换运算符声明中
container由移动构造的新向量container 被破坏了功能返回后:
tmp 由复制构造函数构造我的问题是为什么不是tmp由移动构造函数构造的?
据我所知,函数返回类型是rvalue,应该移动.
请考虑以下代码:
constexpr auto f()
{
auto str = "Hello World!";
return str;
}
int main(int argc, char* argv[])
{
static constexpr auto str = f();
std::cout << str << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是正常的,我的编译器没有显示任何警告?它是否定义了行为?我能保证程序会显示"Hello World!"吗?我希望"Hello World!"不要超出功能范围......
c++ ×9
c++11 ×5
c++14 ×2
c++17 ×2
c ×1
c-strings ×1
c11 ×1
compiler-bug ×1
constexpr ×1
lambda ×1
template-argument-deduction ×1
templates ×1
visual-c++ ×1