如果 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
正确地适用于您的目的:
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);
}
}
};
我有一个序列化函数,可以做类似的事情:
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
正确地适用于您的目的:
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);
}
}
};