Если constexpr время компиляции вылетает из-за неправильной ветки - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть функция сериализации, которая делает что-то вроде:

class Serializer
{
    template<typename T>
    T read(const std::string& source)
    {
        if constexpr(std::is_same<T, int>::value)
        {
            return std::stoi(source);
        }
        else if constexpr(std::is_same<T, float>::value)
        {
            return std::stof(source);
        }
        else
        {
            assert(false);
            return T();
        }
    }
};

Что я хотел бы сделать, это заменить утверждение времени выполнения на утверждение времени компиляции (например, static_assert), чтобы обнаружить, чтореализация отсутствует во время компиляции.Полная специализация функций была бы возможностью обнаружить отсутствующую реализацию, но на самом деле это не вариант для меня, потому что это функция-член, для которой может потребоваться группа членов из инкапсулирующего класса.Есть ли способ сделать что-то вроде статического утверждения, которое не срабатывает, если ветвь constexpr не нажата?

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Поскольку static_assert(false); не зависит от параметров шаблона, компилятор может проверить это утверждение до момента создания экземпляра в двухфазном поиске.Так, например, следующее static_assert правильно работает для вашей цели:

DEMO

class Serializer
{
public:    
    template<typename T>
    T read(const std::string& source)
    {        
        if constexpr(std::is_same<T, int>::value)
        {
            return std::stoi(source);
        }
        else if constexpr(std::is_same<T, float>::value)
        {
            return std::stof(source);
        }
        else
        {
            static_assert(!std::is_same<T, T>::value);
        }
    }
};
0 голосов
/ 28 февраля 2019

static_assert( std::is_same<T, int>::value || std::is_same<T, float>::value ); решает продемонстрированную проблему.

Как правило, нет, ветвь else не может содержать static_assert(false).Вы можете сделать хаки, чтобы разрешить что-то подобное, но они имеют сомнительную законность.

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

Возможно, вы захотите static_assert(!std::is_same<T,void>{}), только чтобы поймать этот угловой случай.;)

...