在类定义中推导嵌入式静态成员函数的返回类型

时间:2018-07-30 20:57:42

标签: c++ c++17 return-type-deduction

我试图在内联函数定义后为返回类型创建别名以存储成员变量。我在下面简化了我的情况(我要别名的实类型比矢量要难得多,而实函数比单线要复杂得多。)

#include <vector>
using namespace std;
struct Test {
    template <typename T>
    static auto GetVector() { return vector<T>(); }

    using VecInt = decltype(GetVector<int>());
    VecInt x;
};

但是,c在using VecInt行上给了我以下错误:

错误:定义了返回类型的函数'GetVector'不能在定义之前使用。

gcc也给我一个类似的错误。奇怪的是,尽管我没有用到它,但是可以编译:

#include <vector>
using namespace std;
struct Test {
    template <typename T>
    static auto GetVector() { return vector<T>(); }

    void dummy() {
        using VecInt = decltype(GetVector<int>());
        VecInt x;
    }
};

是否有一种方法可以在内联定义后使用别名?另外,我可以将GetVector()函数移到该结构的顶部,然后代码将进行编译。但是,我想将其包含在其中。

3 个答案:

答案 0 :(得分:5)

您是否曾经注意到过,即使被调用者比调用者更远离类,您也可以如何从其他成员函数内部调用内联定义的成员函数?起作用的原因是因为编译器采用内联的成员函数定义并将定义移到类的底部,即}部分之后。因此,您实际上有一个隐式的前向声明。

对于类型别名(例如using声明),不是为true。这些声明完全存在于类中。他们不能引用类后面的声明或定义。

由于不能仅通过声明来推断函数的返回值,并且实际定义(推断返回值所需的内容)位于类的末尾,因此using别名无法编译。除了直接声明函数的返回值外,您无能为力。或将类型别名声明为具有所需的类型,然后让函数使用该别名。

答案 1 :(得分:4)

成员函数体是complete-class context,这意味着该类在那里被视为完整的。在成员函数的主体内,名称查找可以找到typedef的任何其他成员函数或数据成员-无论是在函数之前还是之后声明的。

由于GetVector()具有占位符类型,因此它需要等到类完成后才能实例化正文并推断出返回类型。

但是别名声明不是 完整类上下文。您需要确定此时的VecInt ,而课程尚未完成。由于GetVector()需要先完成课程,因此这是行不通的。

您要么需要(a)显式指定GetVector()的返回类型,(b)显式指定VecInt,要么(c)将GetVector()移出此类(使其成为自由函数还是将其移至基类):

#include <vector>

struct TestBase {
    template <typename T>
    static auto GetVector() { return std::vector<T>(); }
};

struct Test : TestBase {
    using VecInt = decltype(GetVector<int>());
    VecInt x;
};

答案 2 :(得分:0)

中间的typedef可以帮助吗?像这样:

#include <vector>
struct Test
{
    template <typename T>
    using MySimplerType = std::vector<T>;

    template <typename T>
    static auto GetVector() { return MySimplerType<T>(); }

    using VecInt = MySimplerType<int>;
    VecInt x;
};