作为函数参数和返回值的不完整类型

Posted

技术标签:

【中文标题】作为函数参数和返回值的不完整类型【英文标题】:Incomplete types as function parameters and return values 【发布时间】:2018-05-28 18:12:49 【问题描述】:

以下代码compiles successfully both with clang++ 5.0.0 and g++ 7.2(带有-std=c++17 -Wall -Wextra -Werror -pedantic-errors -O0 编译标志):

struct Foo;

struct Bar

    Foo get() const;

    void set(Foo);
;

struct Foo

;

Foo Bar::get() const

    return ;


void Bar::set(Foo)




int main()

    Bar bar;

    (void)bar.get();
    bar.set(Foo);

使用不完整类型作为函数参数和返回值是否有效? C++ 上面写了什么?

【问题讨论】:

这基本上是你在任何标题中所做的...... @Jaa-c 听起来可能很傻,但我之前从未在头文件中使用不完整类型作为函数返回类型或参数类型。 这个想法是你不会让每个可能间接包含你的标题的人必须解析它使用的每种类型的完整定义,因为他们可能不要使用需要所述定义的函数。如果他们,那么他们可以自己包含完整的定义。不过,我认为对你的用户的期望是否好,争论会永远激烈地进行。对于内部使用的标头,我会说这是不费吹灰之力。 【参考方案1】:

据我所知,你可以通过以下方式使用不完整类型:

    作为指针; 作为参考;

因为函数的声明没有创建任何对象,所以是合法的。

【讨论】:

【参考方案2】:

使用不完整类型作为函数参数和返回值是否有效? C++ 上面写了什么?

在函数声明中,是的,它是有效的。

[basic.def.odr] 列出类型必须完整的情况。该列表中没有提及函数声明。请注意,对于 T 的参数和返回类型,函数定义确实需要 T 的定义。

【讨论】:

为什么不在标头中定义返回类型T 会有问题?调用者只需要为它添加一个#include,作为一个非常小的不便的回报,你减少了其他人的编译时依赖,因为不是每个需要fun.h的人都可以真正调用这个函数,尤其是当我们在说话的时候关于成员函数。【参考方案3】:

在函数定义中,不能使用不完整类型:[dcl.fct]/12:

函数定义的参数类型或返回类型在函数定义的上下文中不得是不完整的(可能是cv-限定的)类类型,除非该函数被删除。

但是函数声明没有这样的限制。当你定义Bar::getBar::set时,Foo是一个完整的类型,所以程序没问题。

【讨论】:

以上是关于作为函数参数和返回值的不完整类型的主要内容,如果未能解决你的问题,请参考以下文章

函数作为swift4中的类型

好程序员大数据学习路线分享高阶函数

重构:简化函数调用

Kotlin 函数定义

Python 高级变量类型 --- 函数的进阶

13-01高阶函数