C++ 使用返回在另一个翻译单元中定义的占位符类型的函数

C++ 使用返回在另一个翻译单元中定义的占位符类型的函数,c++,auto,c++14,return-type-deduction,translation-unit,C++,Auto,C++14,Return Type Deduction,Translation Unit,我很难理解中描述的auto类型说明符的C++14扩展是如何实现的,具体允许什么 具体地说,标准的一个变化是 如果声明的函数返回类型包含占位符类型,则函数的返回类型将从函数体中的返回语句(如果有)中推导出来 当函数体与声明位于同一个文件中时,很容易看到它是如何工作的;但是考虑头文件声明使用自动占位符但不定义它的方法的情况。如何成功编译包含此头文件但不包含定义方法的文件的翻译单元 例如,给定文件foo.hpp: class foo { public: auto gen_data(); }

我很难理解中描述的
auto
类型说明符的C++14扩展是如何实现的,具体允许什么

具体地说,标准的一个变化是

如果声明的函数返回类型包含占位符类型,则函数的返回类型将从函数体中的返回语句(如果有)中推导出来

当函数体与声明位于同一个文件中时,很容易看到它是如何工作的;但是考虑头文件声明使用<代码>自动<代码>占位符但不定义它的方法的情况。如何成功编译包含此头文件但不包含定义方法的文件的翻译单元

例如,给定文件
foo.hpp

class foo
{
  public:
    auto gen_data();
};
struct data_struct
{
  int a;
  int b;
  int c;
  double x;
  char data[37];
};

auto foo::gen_data()
{
  data_struct d;
  // initialize members in d...
  return d;
}
#include "foo.hpp"

template<typename T>
double get_x(T f)
{
  return f.gen_data().x;
}

int make_and_get_x()
{
  foo f;
  return get_x<foo>(f);
}
…和文件
foo.cpp

class foo
{
  public:
    auto gen_data();
};
struct data_struct
{
  int a;
  int b;
  int c;
  double x;
  char data[37];
};

auto foo::gen_data()
{
  data_struct d;
  // initialize members in d...
  return d;
}
#include "foo.hpp"

template<typename T>
double get_x(T f)
{
  return f.gen_data().x;
}

int make_and_get_x()
{
  foo f;
  return get_x<foo>(f);
}
…和文件
main.cpp

class foo
{
  public:
    auto gen_data();
};
struct data_struct
{
  int a;
  int b;
  int c;
  double x;
  char data[37];
};

auto foo::gen_data()
{
  data_struct d;
  // initialize members in d...
  return d;
}
#include "foo.hpp"

template<typename T>
double get_x(T f)
{
  return f.gen_data().x;
}

int make_and_get_x()
{
  foo f;
  return get_x<foo>(f);
}
#包括“foo.hpp”
模板
双进位x(tf)
{
返回f.gen_data().x;
}
int make_和_get_x()
{
福福;
返回get_x(f);
}
…自行编译
main.cpp
合法吗?若否,原因为何?如果是这样的话,
get_x
是如何实例化的,因为编译器无法知道
gen_data
的返回类型是否有一个名为
x
的成员,更不用说它的偏移量了


这似乎是一个问题,即使不担心模板实例化;例如,如果您尝试直接访问
f.genu data().x
或将其传递给函数,会发生什么情况?

适用规则见§7.1.6.4[dcl.spec.auto]/p11:

如果需要具有未减少占位符类型的实体类型 要确定表达式的类型,程序的格式不正确

有一个例子:

auto f();
void g() { &f; }  // error, f’s return type is unknown

您需要
genu数据的类型来确定表达式的类型
x.genu数据()
;因此,该程序的格式不正确。要使用这样的函数,定义必须对编译器可见。

这是不合法的,因为编译器必须在每个需要它的翻译单元中推导返回类型(对于包含函数调用的表达式的类型)。但是,我不知道如何从标准中推断出这一点。是否有任何证据证明,在需要返回类型的翻译单元中,需要“由编译器”执行推断?那太好了。语言律师可以声称“返回类型是在另一个翻译单元推导出来的”。所以我在寻找一种说法,“未减量”意味着“在当前翻译单元中未减量”。(对于模板实例化,我认为ODR暗示了这一点。)@dyp-Hmm,我明白你的意思。我认为我没有看到任何明确的说法……是的,@dyp的“语言律师”问题或多或少是我在我的问题中想要表达的意思。在链接时没有“未减少的占位符类型”这样的东西;“未减少”必然意味着“在编译过程中的特定点未减少”。标准中是否明确说明了编译器何时需要能够推断未减少占位符的真实类型?