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

If constexpr compile time crash for wrong branch

我有一个序列化函数,可以做类似的事情:

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)替换 运行 时断言,以检测编译时缺少实现。全功能专业化将是检测缺失实现的一个选项,但这对我来说并不是一个真正的选项,因为它是一个成员函数,可能需要来自封装 class 的一堆成员。有没有什么方法可以做一些像静态断言这样的事情,如果没有命中 constexpr 分支,它就不会被触发?

static_assert( std::is_same<T, int>::value || std::is_same<T, float>::value ); 解决了演示的问题。

一般来说,不可以,else 分支中不能有 static_assert(false)。您可以通过 hack 来允许类似的事情,但它们的合法性值得怀疑。

可能最简单的解决方案就是不从 else 中选择 return,并在您的函数没有 return 值时让编译器发出警告。

您可能想要 static_assert(!std::is_same<T,void>{}) 只是为了抓住那个极端情况。 ;)

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