Как я могу объединить вывод типа возвращаемого значения, создание экземпляра шаблона с файлами заголовков? - PullRequest
2 голосов
/ 18 июня 2020

Я хотел бы объединить вывод типа возвращаемого значения и явное создание экземпляра шаблона (например, f<int> вместо template<typename T> f<T>). В приведенном ниже примере показано, как это можно сделать в одном файле воспроизвести с кодом .

#include <type_traits>
#include <iostream>
#include <string>

enum Enum { String, Int };

template <Enum E>
auto f();

template <>
auto f<Enum::String> () {
   return "string";
}

template <>
auto f<Enum::Int> () {
    return 2;
}

int main()
{
    const Enum e = Enum::String;
    auto a = f<e>();
    const Enum g = Enum::Int;
    auto b = f<g>();

    return 0;
}

Вопрос: Как объединить возврат вывод типа, создание экземпляра шаблона с заголовочными файлами?

Что бы я хотел:

// f.hpp
template<Enum E> auto f();
// f.cpp
f<Enum::Int> f() { // ...
// other_file.cpp
#include "f.hpp"
auto a = f<Enum::Int>();

Ошибка: function 'f<Enum::Int>' with deduced return type cannot be used before it is defined.

Идеи:

IMO ошибка имеет смысл, поскольку создание функции не находится в заголовке и, следовательно, не было включено в other_file.cpp.

Я не могу для записи экземпляров в f.hpp, поскольку они являются экземплярами (очевидно).

Я думал об использовании inline, но это не помогло (почему?).

Кто-нибудь может мне помочь?

Ответы [ 2 ]

2 голосов
/ 18 июня 2020

Я думал об использовании inline, но это не помогло (почему?).

относительно ключевого слова inline здесь:

// f.hpp
template<Enum E> auto f();

https://en.cppreference.com/w/cpp/language/definition

В программе может быть более одного определения каждого из следующих: тип класса, тип перечисления, встроенная функция, встроенная переменная (начиная с C ++ 17), шаблонная сущность (шаблон или член шаблона, но не полная специализация шаблона)

короче говоря, вам не нужны встроенные шаблоны (если это не полная специализация)

в этом случае:

// f.cpp
f<Enum::Int> f() { // ...

вам понадобится ключевое слово inline, если оно было в файле заголовка. Для целей ODR эта полная специализация в основном рассматривается как определение функции. Хотя, поскольку это определение находится только в одном файле cpp, в любом случае есть только одно определение, поэтому ключевое слово inline не помогает.

для получения дополнительной информации о встроенных шаблонах см. Также: { ссылка }

1 голос
/ 18 июня 2020

Фактически, два определения, которые вы предоставляете для 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> ();

Внутри f.cpp:

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

template
auto f<Enum::Int> ();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...