如果constexpr的编译时间因错误的分支而崩溃

时间:2019-02-28 18:22:45

标签: c++ constexpr static-assert

我有一个类似的序列化功能:

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 :(得分:3)

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>{})只是为了抓住这种情况。 ;)

答案 1 :(得分:3)

由于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);
        }
    }
};