Перегрузка функции с помощью шаблонов - PullRequest
34 голосов
/ 17 февраля 2020

Я пытаюсь определить функцию, используя шаблоны, и я хочу, чтобы typename было либо int, либо anEnum (спецификацией c enum, которую я определил). Я попробовал следующее, но мне не удалось:

template <int | anEnum T> // or <int T, anEnum T> or <int, anEnum T>
bool isFunction(const T &aVariable){}

Я пытаюсь использовать шаблоны вместо определения двух перегруженных функций. Я бы предпочел, чтобы эта функция вызывалась следующим образом, при этом программисту не нужно учитывать тип

isFunction(aVariable) // and not isFunction<int> (aVariable) nor isFunction<anEnum> (aVariable)

По сути, я хочу, чтобы эта функция была шаблонной для типов int и aNum. Я искал это, но не смог найти ответ. Что я могу пропустить? Спасибо,

Ответы [ 4 ]

25 голосов
/ 17 февраля 2020

В дополнение к ответу, не относящемуся к C ++ 20, если вы, случайно, сможете использовать C ++ 20 и его concepts функцию, я бы Предлагаем вам следующую реализацию:

#include <iostream>
#include <concepts>

enum class MyEnum {
    A,
    B,
    C
};

template <typename T>
concept IntegralOrEnum = std::same_as<MyEnum, T> || std::integral<T>;

template <IntegralOrEnum T>
bool isFunction(T const& aVariable) {
    return true;
}

int main() {
    isFunction(MyEnum::A);
    isFunction(3);
    isFunction("my_string"); // error
    return 0;
}

Демо

ОБНОВЛЕНИЕ

Согласно @ RichardSmith комментарий, вот более масштабируемый и многократно используемый подход:

template <typename T, typename ...U>
concept one_of = (std::is_same_v<T, U> || ...);

template <one_of<int, MyEnum> T>
bool isFunction(T const& aVariable) {
    return true;
}
21 голосов
/ 17 февраля 2020

Есть несколько способов сделать это sh. Все связаны с использованием заголовка type_traits. Например, вы можете указать c на типы, о которых идет речь, в теле функции.

Или, если вам нужно учитывать эту функцию среди других перегрузок, можно использовать технику SFINAE.

template<typename T>
auto isFunction(const T &aVariable) 
  -> std::enable_if_t<std::is_same<T, int>::value || std::is_same<T,anEnum>::value, bool> {
}

Это удалит функцию из набора перегрузки перед вызовом, если типы не совпадают. Но если вам не нужно это поведение, утверждение stati c допускает более понятное сообщение об ошибке для программиста.

3 голосов
/ 18 февраля 2020

А как насчет этого решения? Код с функцией будет скомпилирован, если тип T удовлетворяет вашим требованиям. В противном случае утверждение stati c не будет выполнено.

#include <type_traits>
enum anEnum {
    //
};

template <typename T, bool defined = std::is_same<T, int>::value ||
                                     std::is_same<T, anEnum>::value>
bool isFunction(const T& aVariable)
{
    static_assert(defined, "Invalid specialization");

    bool result = false;
    // Put your code here
    return result;
}
0 голосов
/ 18 февраля 2020

Я улучшил { ссылка } ответ. «Если constexpr» может помочь в этой ситуации:

template <typename T>
struct always_false : std::false_type {};

template <typename T>
bool isFunction(const T& aVariable)
{
    if constexpr(std::is_same_v<T, int> || std::is_same_v<T, anEnum>)
    {
        std::cout << "int\n";
        // put your code here
        return true;
    }
    else
    {
        static_assert(always_false<T>::value, "You should declare non-template function or write if constexpr branch for your type");
        return false;
    }
}

bool isFunction(std::string_view)
{
    std::cout << "std::string_view\n";
    return true;
}

int main()
{
    isFunction(std::string_view("1L"));
    isFunction(1);
    //isFunction(1L); // will produce an error message from static_assert
}

isFunction (1L) потерпит неудачу, потому что нет перегруженной функции или ветки «если constexpr».

ОБНОВЛЕНИЕ: Исправлено пропущено

template <typename T>
struct always_false : std::false_type {};

https://godbolt.org/z/eh4pVn

...