C++ 如何将返回类型推断、模板实例化与头文件结合起来?

C++ 如何将返回类型推断、模板实例化与头文件结合起来?,c++,templates,inline,header-files,return-type-deduction,C++,Templates,Inline,Header Files,Return Type Deduction,我想结合返回类型推断和显式模板实例化(例如,f而不是template f)。下面的示例显示了如何在一个文件中执行此操作 #包括 #包括 #包括 枚举枚举{字符串,Int}; 模板 自动f(); 模板 自动f(){ 返回“字符串”; } 模板 自动f(){ 返回2; } int main() { 常量Enum e=Enum::String; 自动a=f(); 常量Enum g=Enum::Int; 自动b=f(); 返回0; } 问题:如何将返回类型推断、模板实例化与头文件结合起来 我想要的是:

我想结合返回类型推断和显式模板实例化(例如,
f
而不是
template f
)。下面的示例显示了如何在一个文件中执行此操作

#包括
#包括
#包括
枚举枚举{字符串,Int};
模板
自动f();
模板
自动f(){
返回“字符串”;
}
模板
自动f(){
返回2;
}
int main()
{
常量Enum e=Enum::String;
自动a=f();
常量Enum g=Enum::Int;
自动b=f();
返回0;
}
问题:如何将返回类型推断、模板实例化与头文件结合起来

我想要的是:

// f.hpp
template<Enum E> auto f();
//f.hpp
模板自动f();
//f.cpp
f(){/。。。
//other_file.cpp
#包括“f.hpp”
自动a=f();
错误:
带有推断返回类型的函数“f”在定义之前不能使用

创意:

在我看来,这个错误是有意义的,因为函数实例化不在头中,因此没有包含在
other_file.cpp

我无法在
f.hpp
中编写实例化,因为它们是实例化(显然)

我曾想过使用
内联
,但那没有帮助(为什么?)


有人能帮我吗?

实际上,您为
f
提供的两个定义称为显式专门化。您不能在专用实现文件中定义它们,因为编译器必须知道它们的返回类型

在这种情况下,如果要使用推断返回类型,可能的解决方法是使用constexpr if语句将专门化定义打包到主模板定义中,然后使用显式模板实例化:

f.hpp

enum Enum { String, Int };

template <Enum E>
auto f(){
    if constexpr (E==String)
       return "string";
    else
       return 2;
}

extern template
auto f<Enum::String> ();

extern template
auto f<Enum::Int> ();
#include "f.hpp"
template
auto f<Enum::String> ();

template
auto f<Enum::Int> ();
我考虑过使用内联,但那没有帮助(为什么?)

关于此处的内联关键字:

// f.hpp
template<Enum E> auto f();
//f.hpp
模板自动f();

一个程序中可以有以下每种类型的多个定义:类类型、枚举类型、内联函数、内联变量(自C++17以来)、模板化实体(模板或模板成员,但不是完全模板专用化)

简言之,模板不需要内联(除非是完全专门化)

在这种情况下:

// f.cpp
f<Enum::Int> f() { // ...
//f.cpp
f(){/。。。
如果是在头文件中,则需要内联关键字。出于ODR目的,此完全专门化基本上被视为函数定义。尽管此定义仅在一个cpp文件中,但仍然只有一个定义,因此内联关键字没有帮助


<> >更多的信息,请参阅:

好!我尝试了<代码> COSTEXPR,如果它自己的代码是不可见的,我不知道我必须将它与显式的专业化相结合。我也使用C++ 17。Extn是保留的,但没有意义,正确的,不必。注意术语“显式特化”和“显式实例化”。这两个术语的含义并不相同。在你的问题中,你做了一个“显式专门化”“:为特定模板参数提供定义。模板实例化是指当您要求编译器使用泛型定义为给定模板参数生成实例时。需要
extern
。这意味着后面是一个声明。没有extern,显式实例化就是一个定义。”。
#include "f.hpp"
template
auto f<Enum::String> ();

template
auto f<Enum::Int> ();
// f.hpp
template<Enum E> auto f();
// f.cpp
f<Enum::Int> f() { // ...