在(模板)参数中的前向声明(使用elaborated type specifier)和“普通”前向声明之间有什么区别?
void foo(struct bar *);
// vs
struct bar;
void foo(bar *);
// ------ and also -------
std::unique_ptr<class Baz> one;
// vs
class Baz;
std::unique_ptr<Baz> two;
字符串
在(模板)参数中的前向声明(使用elaborated type specifier)和“普通”前向声明之间有什么区别?
void foo(struct bar *);
// vs
struct bar;
void foo(bar *);
// ------ and also -------
std::unique_ptr<class Baz> one;
// vs
class Baz;
std::unique_ptr<Baz> two;
字符串
3条答案
按热度按时间vxqlmq5t1#
让我们开始注意到“前向声明”是一种口语,用来指某些类型的声明的某种常见的实际用途。就C++标准而言,没有前向声明这样的东西。只有声明。
考虑到这一点,我认为,
字符串
和
型
就它们对名称
bar
的影响而言。如果之前没有这样做的声明,那么这两个声明最终都会引入结构bar
的名称。C++17中的相关段落似乎是[basic.lookup.elab]/2(重点是我的):
如果 elaborated-type-specifier 是由 class-key 引入的,并且这个查找没有找到之前声明的 type-name,或者[...]**,则 elaborated-type-specifier 是一个引入 *class-name * 的声明,如[basic.scope.pdecl]中所述。
如果遇到不包含 nested-name-specifier 的 elaborated-type-specifier,则执行非限定名称查找以查看该名称是否已经命名了相应的类型。如果没有找到以前声明的名称,则 elaborated-type-specifier 成为该名称的类类型的声明.
正如geza所指出的那样,可能存在差异的一种方式与引入名称的范围有关。
型
总是将名称引入声明出现的作用域中,作为任何其他类型声明的一部分出现的 elaborated-type-specifier 将名称引入最近的封闭命名空间[basic.scope.pdecl]/7。
fdbelqdn2#
不同之处可能是声明引入的作用域。在精心设计的类型说明符的情况下,声明被引入到最近的命名空间中,这可能会造成差异。
举例来说:
字符串
在这里,
Bar
是在全局命名空间中声明的,而不是在Foo
中声明的。50pmv0ei3#
如果你没有事先声明
struct bar;
,那么struct bar
可能会引用在外部作用域中声明的类型名(可能来自一个完全不同的库)。例如:字符串
^这里
foo
的参数是指向全局作用域中的类bar
的指针。型
^这里
foo
的参数是指向ns::bar
的指针。