小编cpp*_*ner的帖子

使用列表初始化调用Ambigous构造函数

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)被召唤,为什么在这种情况下它是模棱两可的?

c++ c++11 list-initialization

13
推荐指数
1
解决办法
801
查看次数

为什么boost :: filesystem :: path和std :: filesystem :: path缺少operator +?

考虑以下关于路径分解的断言,其中每个局部变量例如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")和 …

c++ boost-filesystem c++17

13
推荐指数
1
解决办法
670
查看次数

覆盖说明符作为模板参数 - 它有效吗?

我有以下代码不能在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++ compiler-bug c++11

12
推荐指数
2
解决办法
814
查看次数

显式构造函数和嵌套初始化列表

以下代码成功编译了大多数现代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)

c++ overload-resolution c++11 list-initialization

10
推荐指数
1
解决办法
1130
查看次数

为什么不可变的lambda捕获可以被移动?

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)

c++ lambda move-semantics c++14

10
推荐指数
1
解决办法
518
查看次数

g ++ c ++ 17类模板参数推导不适用于非常具体的情况

我有以下代码:

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

10
推荐指数
2
解决办法
421
查看次数

为什么拥有私有基类的声明会使类型名称无法访问?

令我感到惊讶的是,在下面的示例中,声明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)

c++ injected-class-name

10
推荐指数
1
解决办法
202
查看次数

如果您知道在到达有效区域的末尾之前找到该字符,那么调用长度过长的memchr是否合法?

在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标准,但如果不是这样的话我想知道.

c language-lawyer c++11 c11

9
推荐指数
1
解决办法
406
查看次数

C++ 11移动语义和右值引用

请考虑以下代码:

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转换运算符声明中

  1. container由移动构造的新向量
  2. container 被破坏了

功能返回后:

  1. tmp 由复制构造函数构造

我的问题是为什么不是tmp由移动构造函数构造的?

据我所知,函数返回类型是rvalue,应该移动.

c++ visual-c++ c++11 visual-studio-2013

8
推荐指数
1
解决办法
269
查看次数

在constexpr函数中返回一个C字符串:为什么编译器没有警告?

请考虑以下代码:

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++ c-strings string-literals constexpr c++14

8
推荐指数
2
解决办法
642
查看次数