c++ - 这段编译良好的荒谬代码是 Clang 和 GCC 中的错误吗?

标签 c++ c++11 g++ clang language-lawyer

<分区>

我今天在研究模板,看看能否让编译器从其内部类之一推断出外部类的类型。 我没有找到我的解决方案(我怀疑这是不可能的),但是在尝试修复错误时我遇到了非常奇怪的行为,我将其简化为以下代码片段。

struct A
{
    struct B{};

    template <typename T>
    struct EverythingIsFine
    {
        using Outer = T;
        using Inner = typename T::B::B::B::B::B::B;
    };

    using ItWillBeOkay = EverythingIsFine<B>; // Probably not ok
    using InnerProblem = ItWillBeOkay::Inner; // Still not ok
    using OuterProblem = decltype(B().ItWillBeOkay::Outer::B::B::B
                                     ::B::B::B::~B()); // Not even CLOSE to ok
};

令人惊讶的是,它在 Clang 和 GCC 中都没有警告和错误编译。
我的编译器版本是 gcc version 5.3.1 20160121 (Debian 5.3.1-7)Debian clang version 3.6.2-3 (tags/RELEASE_362/final) (based on LLVM 3.6.2)用于编译的标志是 -std=c++11 -Wall -Wextra .

我观察到它也编译得很好 on Ideone with the C++14 setting .


然后我使用这个简单的测试来获取 InnerProblem 的确切类型和 OuterProblem :

template <class T> void Type();
int main()
{
    Type<A::InnerProblem>();
    Type<A::OuterProblem>();
}

并且两个编译器在编译测试时报告相同的类型:

In function main:
main.cpp:20: undefined reference to void Type<A::B>()
main.cpp:21: undefined reference to void Type<void>()

也就是InnerProblem的类型是A::BOuterProblem 的类型是void .


这是标准以某种方式允许的,还是两个编译器中的错误?
由于我似乎和我的编译器一样困惑,这段代码到底发生了什么?

编辑:作为简化的跟进,因为我不明白为什么两个编译器不能给出相同的结果,下面的代码使用 Clang 编译,而不是 GCC。

struct A
{
    struct B{};

    template <typename T>
    struct EverythingIsFine
    {
        using Inner = typename T::B::B::B;
    };

    using Problem = EverythingIsFine<B>::Inner::B::B::B; // Not ok
};

GCC 现在输出以下错误:

main.cpp:11:26: error: 'A::B::B' names the constructor, not the type using InnerProblem = EverythingIsFine::Inner::B::B::B; // Not ok

最佳答案

这是有效的。

The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name." (9/2).

因此 B::B 将类命名为 BB::B::B 也是如此,依此类推。

编辑:

因此 typename B::B 将类命名为 Btypename B::B::B 也是如此,依此类推。

关于c++ - 这段编译良好的荒谬代码是 Clang 和 GCC 中的错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35162397/

相关文章:

c++ - 跳过输入流值

c++ - 隐式构造函数可用于从 Base 派生的所有类型,但当前类型除外?

c++ - 将 lambda 转换为 std::tr1::function

c++ - 转发到就地构造函数

c++ - 包含许多 "if"的关键循环,其输出为常量 : How to save on condition tests?

c++ - g++ -O 优化

qt - 将 -std=gnu++11 编译器标志添加到 QMake

c++ - 如何使 QtCreator 使用 gsl 库进行编译?

c++ - C/C++ 逗号运算符让我困惑。语言律师?

c++ - 为什么可以重新设置引用参数?