Как вернуть разные типы на основе проверки std :: is_same - PullRequest
0 голосов
/ 05 июня 2018

Рассмотрим следующий код:

template<typename T>
T foo() {
    if (std::is_same<T, int>::value)
        return 5;

    if (std::is_same<T, std::string>::value)
        return std::string("bar");

    throw std::exception();
}

При вызове с foo<int>() выдается ошибка cannot convert ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘int’ in return.

Я знаю, что решение заключается в использовании специализации шаблона, но яспрашиваю, возможно ли как-то сохранить текущий механизм с проверкой типа через std::is_same?

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

В компиляторе до C ++ 17 вы можете использовать диспетчеризацию тегов, чтобы получить то, что вам нужно.

template <typename T> tag_t {};

int foo(tag_t<int> t) { return 5; }

std::string foo(tag_t<std::string> t) { return "bar"; }

template<typename T>
T foo() {
    return foo(tag_t<T>());
}
0 голосов
/ 05 июня 2018

Обе ветви if должны быть действительны во время компиляции, даже если одна из них никогда не выполняется.

Если у вас есть доступ к C ++ 17, измените if s наif constexpr:

template<typename T>
T foo() {
    if constexpr (std::is_same<T, int>::value)
        return 5;

    if constexpr (std::is_same<T, std::string>::value)
        return std::string("bar");

    throw std::exception();
}

До C ++ 17 вам придется эмулировать это с помощью специализации шаблона:

template<typename T>
T foo()
{
    throw std::exception();
}

template <>
int foo<int>() {
    return 5;
}

template <>
std::string foo<std::string>() {
    return "bar";
}

Если ваш реальный foo выполняет больше работы, чем этотНапример, если его специализация приведет к дублированию кода, вы можете ввести вспомогательную функцию, которая будет инкапсулировать только операторы return / throw, и специализировать ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...