小编Bel*_*loc的帖子

GCC拒绝使用enum-base进行简单声明; clang接受了 - 这是正确的吗?

GCC 4.9.2不编译此代码段,但是clang 3.5.0可以编译.哪一个是正确的?

enum F : int { x, y, z};
int F;
enum F:int f = F::x;
Run Code Online (Sandbox Code Playgroud)

GCC输出:

main.cpp:3:12: error: expected ';' or '{' before 'f'
 enum F:int f = F::x;
            ^
main.cpp:3:12: error: expected class-key before 'f'
main.cpp:3:14: error: invalid type in declaration before '=' token
 enum F:int f = F::x;
              ^
main.cpp:3:16: error: 'F' is not a class, namespace, or enumeration
 enum F:int f = F::x;
                ^
Run Code Online (Sandbox Code Playgroud)

我相信GCC是正确的,因为一个简单声明(包含精心设计的类型说明符enum F)不允许使用enum-base …

c++ enums language-lawyer c++11 c++14

24
推荐指数
2
解决办法
836
查看次数

C++标准中短语"构造函数没有名称"的含义

在尝试理解C++标准中的"构造函数没有名称"这一短语时,似乎我在clang中发现了一个错误.有人能证实吗?

VS2015 gcc拒绝这段代码,而且我认为他们是正确的.至少,这是我从N4140的§12.1[class.ctor]/2得到的印象:

#include <iostream>
class A {
public:
    A() { std::cout << "A()" << '\n'; }
};

int main()
{
  A::A();
}
Run Code Online (Sandbox Code Playgroud)

N4140中的§12.1[class.ctor]/2:

构造函数用于初始化其类类型的对象.因为构造函数没有名称,所以在名称查找期间永远不会找到它们; ...

使用A::A();上面的表达式,clang通过名称查找找到构造函数,A而不是它应该找到类型名称.查看实例.

c++ clang language-lawyer c++14

22
推荐指数
2
解决办法
795
查看次数

为什么B :: f不解决歧义,但A :: f呢?

为什么B :: f不解决歧义,但A :: f呢?

namespace A
{
    class X { };
    void f( X );
} 

namespace B
{
    void f( A::X );
    void g( A::X x )
    {
        using B::f;   // which expression shall I use here to select B::f?
        f(x);         // ambiguous A::f or B::f
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ argument-dependent-lookup

19
推荐指数
2
解决办法
518
查看次数

使用声明不能在功能范围内重复.这是为什么?

在[namespace.udecl]/10中,您有以下示例:

namespace A {
    int i;
}
namespace A1 {
    using A::i;
    using A::i; // OK: double declaration
}
void f() {
    using A::i;
    using A::i; // error: double declaration
}
Run Code Online (Sandbox Code Playgroud)

这个片段编译成clang.

c++ using-declaration language-lawyer c++14

18
推荐指数
1
解决办法
247
查看次数

为什么从构造函数对纯虚函数的虚拟调用是UB,标准允许调用非纯虚函数?

从10.4 抽象类 parag.标准中的6:

"可以从抽象类的构造函数(或析构函数)调用成员函数;直接或间接地对从这样的构造函数(或析构函数)创建(或销毁)的对象进行纯虚函数的虚拟调用的效果未定义."

假设标准允许从构造函数(或析构函数)调用非纯虚函数,为什么区别?

[编辑]关于纯虚函数的更多标准引用:

§10.4/ 2通过在类定义中的函数声明中使用纯说明符(9.2)来指定虚函数.只有在使用(12.4)qualified-id语法(5.1)调用时,才需要定义纯虚函数.... [注意:函数声明不能​​同时提供纯指定符和定义-end note]

§12.4/ 9 析构函数可以声明为虚拟(10.3)或纯虚拟(10.4); 如果在程序中创建了该类或任何派生类的任何对象,则应定义析构函数.

一些需要回答的问题是:

  • 如果纯虚函数没有给出实现,那么这不应该是编译器或链接器错误吗?

  • 在为纯虚函数赋予实现的情况下,为什么在这种情况下不能很好地定义它来调用这个函数?

c++ standards pure-virtual

17
推荐指数
1
解决办法
8240
查看次数

什么是微不足道的功能?

[basic.def.odr]/3引用了术语"非平凡函数",其定义在标准(N4140)中找不到.

[basic.def.odr]/3

变量x的名称显示为潜在评估的表达式ex,除非将lvalue-to-rvalue转换(4.1)应用于x,否则将生成一个不调用任何非平凡函数的常量表达式(5.19),并且,如果x是一个对象,ex是表达式e的潜在结果集合的元素,其中左值到右值的转换(4.1)应用于e,或者e是丢弃值表达式(第5节).

c++ language-lawyer c++14

16
推荐指数
1
解决办法
3459
查看次数

我相信clang错误地允许内联友人函数访问封闭范围内的数据.gcc和vs2013都拒绝此代码

friend函数f无权访问封闭类的私有成员A.

#include <iostream>

class A{
    const static int p = 1;
    class B {
        friend void f() {
            std::cout << p << '\n';
            std::cout << q << '\n';
        }
    };
public:
    const static int q = 2;
};
void f();

int main()
{
    f();
}
Run Code Online (Sandbox Code Playgroud)

至少,这是我认为N4140中的[class.nest]/4所说的(见下文).

§9.7/ 4

与成员函数一样,嵌套类中定义的友元函数(11.3)位于该类的词法范围内; 它遵循与名称绑定相同的规则作为该类的静态成员函数(9.4),但它对封闭类的成员没有特殊的访问权限.

实例

c++ friend clang clang++ c++14

14
推荐指数
1
解决办法
231
查看次数

移动构造函数在下面显示的代码段中是否有任何特殊原因?

抛出对象后,gcc,clang和VS2015不会在下面的代码中忽略对move构造函数的调用a.在我看来,满足§8.12[class.copy]/31(N4140)的项目符号(31.2)中确定的条件.

#include <iostream>

struct A
{
    A() { std::cout << "Default ctor " << '\n'; }
    A(const A& a) { std::cout << "Copy ctor" << '\n'; }
    A(A&& a) { std::cout << "Move ctor" << '\n'; }
    ~A() { std::cout << "Destructor " << '\n'; }
};

int main()
{
    try
    {
        A a;
        throw a;
    }
    catch(A& a) { std::cout << "Caught" << '\n'; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这a是一个左值,但根据§12.8/ 32,首先执行重载决策以选择副本的构造函数,就像对象由rvalue指定一样.也就是说,对move构造函数的调用是可以的.如果删除上面的移动构造函数的定义,则调用复制构造函数,但同样,它不会被省略!

我理解标准没有规定复制省略,但我很想知道是否有任何特殊条件可以证明这一事实,上面提到的三个编译器在这个特定的例子中避免了这种优化.

gcc的示例输出,来自上面的链接:

g ++ -std …

c++ exception copy-elision c++14

14
推荐指数
1
解决办法
256
查看次数

typeid不适用于非静态成员函数

clang不编译typeid下面的第三个调用(参见实例).但我在§5.2.8中看不到任何禁止这一点的内容,特别是当我们认为表达式B::f不是多态类类型的glvalue时(见第3段).此外,根据此段,表达式B::f是未评估的操作数,因此,调用typeid(B::f)应该编译.请注意,GCC不会编译以下任何调用typeid:

#include <iostream>
#include <typeinfo>

struct A{ int i; };
struct B{ int i; void f(); };

int main()
{
    std::cout << typeid(A::i).name() << '\n';
    std::cout << typeid(B::i).name() << '\n';
    std::cout << typeid(B::f).name() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

c++ typeid language-lawyer c++11

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

C++语法的两个好奇心

§5.2[expr.post]/1中,我们有了expression-list的定义

expression-list:
     initializer-list

为什么我们需要这两个定义?

§8.5[dcl.init]/1中,我们有:

braced-init-list:
     {initializer-list,opt }
     {}

为什么我们需要,上面的可选项?

请注意,此代码段编译:

struct A{
    int i;
    float f;
    A(int i, float f) : i(i), f(f) {}
};

int main()
{
    A a = { 1, 2., };
}
Run Code Online (Sandbox Code Playgroud)

c++ grammar language-lawyer c++14

13
推荐指数
2
解决办法
1304
查看次数