Автоматическое удержание типа c с использованием is_same_v - PullRequest
4 голосов
/ 30 января 2020

У меня есть некоторый код в шаблоне, подобный так:

if constexpr ( std::is_same_v<T, CompletedGeneration> ) {
    auto stat = stats->getGenerationStats();
} else if constexpr ( std::is_same_v<T, CompletedReset> ) {
    auto stat = stats->getResetStats();
} else if constexpr ( std::is_same_v<T, CompletedRun> ) {
    auto stat = stats->getRunStats();
} else {
    static_assert( false, "Invalid type for helper function" );
}

auto для stat был только для того, чтобы заставить его временно скомпилироваться. stats имеет тип T

После этого оператора if есть набор кода, который опирается на stat, поэтому, очевидно, я не могу определить его в части if. Мне интересно, как бы я go определил его вне if, поскольку его тип зависит от типа параметра шаблона T (но не сам T)?

Нужно ли указывать дополнительный параметр шаблона U, который принимает тип для stat? Или нужно использовать какое-то наследство? Обе эти опции я бы предпочел избежать.

Ответы [ 2 ]

10 голосов
/ 30 января 2020

Вы можете обернуть его в немедленно вызванное лямбда-выражение

auto stat = [&] {
    if constexpr ( std::is_same_v<T, CompletedGeneration> ) {
        return stats->getGenerationStats();
    } else if constexpr ( std::is_same_v<T, CompletedReset> ) {
        return stats->getResetStats();
    } else if constexpr ( std::is_same_v<T, CompletedRun> ) {
        return stats->getRunStats();
    }
}();

Это также устраняет необходимость в опрометчивом static_assert(false), который теперь заменяется на stat имеющий неверный тип void.

2 голосов
/ 30 января 2020

Вы можете использовать черту типа:

template <typename T>
struct stats_type;

template <>
struct stat_type<CompletedGeneration> {
    using type = decltype(std::declval<T>().getGenerationStats());
};

// and similar for the other cases

Тогда правильный тип для stat будет просто stat_type<T>::type;

Однако, возможно, это немного старая школа и слишком много шаблонного. Я просто хотел упомянуть об этом для полноты картины. С другой стороны, если вы поместите соответствующий вызов функции в конструктор stat_type, тогда вы можете заменить весь constexpr if-else одной строкой stats_type<T>::type stat{stats};.

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