考虑
using foo = int;
struct A {
typedef A (foo)();
};
Run Code Online (Sandbox Code Playgroud)
GCC 和 ICC 接受该代码段,而 Clang 和 MSVC 拒绝它。Clang 的错误信息是
Run Code Online (Sandbox Code Playgroud)<source>:4:15: error: function cannot return function type 'void ()' typedef A (foo)(); ^ <source>:4:13: error: typedef name must be an identifier typedef A (foo)(); ^ 2 errors generated.
MSVC 说
Run Code Online (Sandbox Code Playgroud)<source>(4,15): error C2091: function returns function typedef A (foo)(); ^
(现场演示)
为什么 Clang 和 MSVC 会产生这个错误?哪些编译器是正确的?
(我专门从标准或任何缺陷报告中寻找报价。)
请考虑以下代码:
struct Foo {
struct Bar;
Foo()
{
Bar bar; // Why isn't Bar an incomplete type?!
}
struct Bar {}; // Full definition
};
// struct Bar {}; // fails to compile due to incomplete type
int main()
{
Foo foo;
}
Run Code Online (Sandbox Code Playgroud)
它在至少2个编译器(gcc5.2,clang3.5)下编译得很好.我的问题是:
Bar在构造函数中不被认为是不完整的类型Foo::Foo,因为我将它在构造函数上方转发声明但在构造函数中完全使用它?每当我走出Foo::Bar课堂之外,换句话说,Bar成为一个独立的课程,我得到了预期
错误:聚合'Foo :: Bar bar'的类型不完整,无法定义
我甚至不知道该去哪里.谷歌不是很有帮助.和我之前的问题一样.我正在使用TextMate的Command + R来编译项目.
game.h:16:错误:'Player*HalfSet :: Player()const'的声明
players.h:11:错误:从'class Player'改变'Player'的含义
game.h:21:错误:'播放器'不是一种类型
player.h文件(部分)
#ifndef PLAYERS_H
#define PLAYERS_H
using namespace std;
#include <string>
#include <vector>
#include <istream>
#include <iomanip>
#include "generics.h"
class Player{ //Line 11
public:
//getters
long Id() const;
string FirstName() const;
string LastName() const;
string Country() const;
//setters
void setId(long id);
void setFirstName(string s);
void setLastName(string s);
void setCountry(string s);
//serializing functions
void display(ostream &out);
void read(istream &in);
void write(ostream &out);
//Initalizers
Player();
Player(istream &in);
Player(string firstName, string lastName);
Player(string firstName, string …Run Code Online (Sandbox Code Playgroud) 我想要一个struct包含一个类型别名到另一个类型用于元编程目的:
struct Foo {};
struct WithNestedTypeAlias {
using Foo = Foo;
};
Run Code Online (Sandbox Code Playgroud)
然后我可以像WithNestedTypeAlias::Foo模板等那样做.
据我所知,这种类型的别名是有效的,因为它不会改变Foo类型的含义.Clang愉快地编译了这个.
然而,海湾合作委员会抱怨:
test-shadow-alias.cpp:4:20: error: declaration of ‘using Foo = struct Foo’ [-fpermissive]
using Foo = Foo;
^
test-shadow-alias.cpp:1:8: error: changes meaning of ‘Foo’ from ‘struct Foo’ [-fpermissive]
struct Foo {};
^
Run Code Online (Sandbox Code Playgroud)
现在我很困惑,因为我明确没有改变Foofrom 的含义struct Foo.
C++ 14的正确行为是什么?我知道我可以通过重命名来解决这个问题struct Foo,但是我想知道GCC的错误是否正确.
笔记:
使用clang ++ 3.8和gcc 5.4进行测试,但Godbolt建议在最近的GCC版本中没有改变.
我查看了decltype和类成员名称之间的交互阴影外部名称,其中变量的名称可以指外部作用域中的变量或类成员.相比之下,我的问题是关于类型别名.由于Foo总是::Foo在类范围内引用,因此没有歧义.我看不出那里的答案如何适用于我的问题.
这可能是由于误解了实际上是什么类型的别名.
N3337是C++标准的工作草案,发布于2012-01-16:
它只对官方C++ 11标准进行了少量的编辑性修改.
N3337在2012-02-28被修改为N3376:
N3376在2012-11-02被修改为N3485:
我有兴趣知道N3337和N3485之间的区别吗?(或等效地说明N3337和N3376之间的差异以及N3376和N3485之间的差异)
一种方法是尝试分析以下的git日志:
另一种方法是将PDF转储到文本并diff在其上运行.
是否有更好的方法来跟踪这些变化?在某处保留了一系列精选的变更清单吗?也许在标准位置或标准格式?
以下代码
#include <iostream>
typedef double A; // a global typedef
template <class Z> struct B // a template class...
{
A i{22.2}; // global typedef is in scope
typedef int A; // now a local typedef with the same name is introduced
A b{24}; // now the local typedef is in scope
Z c{36}; // a simple member of the template type
};
template <class Z> struct C : B<Z> // a template struct inheriting B
{
A a; // …Run Code Online (Sandbox Code Playgroud) 我最近回答了一个涉及违反C++ 14标准草案的问题:N4140部分3.3.7 类范围段落1规则2说:
在类S中使用的名称N应在其上下文中引用相同的声明,并在完成的S范围内重新评估.违反此规则不需要诊断.
当时的规则3似乎也很重要,它说:
如果类中的重新排序成员声明在(1)和(2)下产生备用有效程序,则程序格式错误,不需要诊断.
我最初的反应是,规则3似乎是多余的,实际上只是对规则的澄清,2并不涵盖任何尚未涵盖的案例.导致备用有效程序的重新排序也必须违反规则2.
那么规则是3多余的还是有一些边缘情况需要两个规则?
c++ ×7
c++11 ×2
c++14 ×2
typedef ×2
clang++ ×1
g++ ×1
name-lookup ×1
scope ×1
type-alias ×1
xcode ×1