<分区>
我今天在研究模板,看看能否让编译器从其内部类之一推断出外部类的类型。 我没有找到我的解决方案(我怀疑这是不可能的),但是在尝试修复错误时我遇到了非常奇怪的行为,我将其简化为以下代码片段。
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 tovoid Type<A::B>()
main.cpp:21: undefined reference tovoid Type<void>()
也就是InnerProblem
的类型是A::B
和 OuterProblem
的类型是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