Почему std :: arrays нарушают шаблонные функции при проверке типов? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть функция шаблона, которая выполняет определенные действия в зависимости от предоставленного типа:

template<typename T>
T read()
{
    if (std::is_integral<T>()) {
        return static_cast<T>(std::stoi(readToken()));
    }
    else if (std::is_same<T, float>()) {
        return std::stof(readToken());
    }
    else if (std::is_same<T, std::array<float, 3>>()) {
        return { read<float>, read<float>, read<float> };
    }
    else throw std::logic_error("Invalid type");
}

При вызове read<int>() компилятор выдает следующее предупреждение:

control достигает конца не пустой функции

1 Ответ

1 голос
/ 23 апреля 2020

read это шаблон. Каждый раз, когда создается этот шаблон, компилятором генерируется все тело функции. При вызове read<int>() раздел с array также компилируется, но невозможно присвоить массив возвращаемому типу, который равен int. Вот почему вы получаете ошибку.

В g ++ 7.3 вы можете использовать , если constexpr конструкция. При этом строки в области действия , если условие истинно, компилируются только:

template<typename T>
T read() {
    if constexpr (std::is_integral<T>()) {
        return static_cast<T>(std::stoi(readToken()));
    }
    else if constexpr (std::is_same<T, float>()) {
        return std::stof(readToken());
    }
    else if constexpr (std::is_same<T, std::array<float, 3>>()) {
        std::array<float, 3> arr;
        arr.at(0) = 4; arr.at(1) = 2; arr.at(2) = 0;
        return arr;
    }
    else throw std::logic_error("Invalid type");
}

До c ++ 17 вы вызываете вспомогательную функцию, которая перегружена для всех типов, которые вы хотите обрабатывать:

template<class T>
T readHelper() {
    throw std::runtime_error("invalid type");
}

// here provide types you want to be handled
template<>
int readHelper<int>() {  return std::stoi(readToken());  }

template<>
float readHelper<float>() { return std::stof(readToken()); }

template<>
std::array<float,3> readHelper<std::array<float,3>>() {
    return std::array<float,3>{};
}

template<class T>
T read2(){
    return readHelper<T>();
}

Демо

...