如果 compile-time-constant 参数错误,则生成编译时错误
Generate compile-time error if compile-time-constant parameter is wrong
我正在尝试编写一个函数,如果使用编译时常量参数调用,如果参数值与 static_assert
不匹配,它将触发编译时错误,但可以仍会在 运行 时使用计算值调用。
有点像这样:
template<int N> void f(N){
static_assert(N == 5, "N can only be 5.");
do_something_with(N);
}
void f(int N){
if(N == 5){
do_something_with(N);
}
}
volatile int five = 5;
volatile int six = 6;
int main() {
f(5); //ok
f(6); //compile-time error
f(five); //ok
f(six); //run-time abort
return 0;
}
我该怎么做?
此外,如果可能的话,我希望能够保留简单的 f(something)
语法,因为此代码适用于不熟悉模板语法的初级程序员应该可以使用的库。
我能想到的最好的是 constexpr
抛出异常的函数。
如果在编译时执行,throw
会导致编译错误;如果在运行时执行,抛出异常
有点像
#include <stdexcept>
constexpr int checkGreaterThanZero (int val)
{ return val > 0 ? val : throw std::domain_error("!"); }
int main()
{
// constexpr int ic { checkGreaterThanZero(-1) }; // compile error
int ir { checkGreaterThanZero(-1) }; // runtime error
}
-- 编辑--
正如 yuri kilocheck 所指出的,您可以调用 std::abort()
而不是抛出异常;举个例子
constexpr int checkGreaterThanZero (int val)
{ return val > 0 ? val : (std::abort(), 0); }
使用不同的语法,你可以这样做:
template <int N>
using int_c = std::integral_constant<int, N>;
namespace detail {
template <std::size_t N>
constexpr int to_number(const int (&a)[N])
{
int res = 0;
for (auto e : a) {
res *= 10;
res += e;
}
return res;
}
}
template <char ... Ns>
constexpr int_c<detail::to_number({(Ns - '0')...})> operator ""_c ()
{
return {};
}
#if 1 // Write this way
// Compile time
template <int N> void f(int_c<N>) = delete;
void f(int_c<5>) { do_something_with(5); }
#else // Or like this
// Compile time
template <int N>
void f(int_c<N>)
{
static_assert(N == 5, "!");
do_something_with(N);
}
#endif
// Runtime
void f(int N){
if (N == 5) {
std::abort(); // Or any other error handling
}
f(5_c);
}
int main(){
f(5_c); // ok
// f(6_c); // Won't compile
f(5); // ok
f(6); // abort at runtime
}
我正在尝试编写一个函数,如果使用编译时常量参数调用,如果参数值与 static_assert
不匹配,它将触发编译时错误,但可以仍会在 运行 时使用计算值调用。
有点像这样:
template<int N> void f(N){
static_assert(N == 5, "N can only be 5.");
do_something_with(N);
}
void f(int N){
if(N == 5){
do_something_with(N);
}
}
volatile int five = 5;
volatile int six = 6;
int main() {
f(5); //ok
f(6); //compile-time error
f(five); //ok
f(six); //run-time abort
return 0;
}
我该怎么做?
此外,如果可能的话,我希望能够保留简单的 f(something)
语法,因为此代码适用于不熟悉模板语法的初级程序员应该可以使用的库。
我能想到的最好的是 constexpr
抛出异常的函数。
如果在编译时执行,throw
会导致编译错误;如果在运行时执行,抛出异常
有点像
#include <stdexcept>
constexpr int checkGreaterThanZero (int val)
{ return val > 0 ? val : throw std::domain_error("!"); }
int main()
{
// constexpr int ic { checkGreaterThanZero(-1) }; // compile error
int ir { checkGreaterThanZero(-1) }; // runtime error
}
-- 编辑--
正如 yuri kilocheck 所指出的,您可以调用 std::abort()
而不是抛出异常;举个例子
constexpr int checkGreaterThanZero (int val)
{ return val > 0 ? val : (std::abort(), 0); }
使用不同的语法,你可以这样做:
template <int N>
using int_c = std::integral_constant<int, N>;
namespace detail {
template <std::size_t N>
constexpr int to_number(const int (&a)[N])
{
int res = 0;
for (auto e : a) {
res *= 10;
res += e;
}
return res;
}
}
template <char ... Ns>
constexpr int_c<detail::to_number({(Ns - '0')...})> operator ""_c ()
{
return {};
}
#if 1 // Write this way
// Compile time
template <int N> void f(int_c<N>) = delete;
void f(int_c<5>) { do_something_with(5); }
#else // Or like this
// Compile time
template <int N>
void f(int_c<N>)
{
static_assert(N == 5, "!");
do_something_with(N);
}
#endif
// Runtime
void f(int N){
if (N == 5) {
std::abort(); // Or any other error handling
}
f(5_c);
}
int main(){
f(5_c); // ok
// f(6_c); // Won't compile
f(5); // ok
f(6); // abort at runtime
}