仅为编译时参数禁用函数
Disable function only for compile-time argument
我想为任何编译时评估的参数(文字,或来自 constexpr 表达式的东西)禁用一个函数。这可能吗?
对于整数,可以使用非类型模板参数执行相反的操作,但这也会改变调用语法。
我正在玩严格的整数,需要以某种方式启动。当前处理错误输入的规则:
如果源值仅在运行时已知,并且缩小转换会破坏解释(而不是位),则会抛出异常
如果源值在编译时已知,但它不适合应该是编译错误。
我的想法是禁用接受所有 constexpr 参数的更宽类型的构造函数。
所谓严格,是指只允许保值转换:
假设 N >= M
int<M>
到 int<N>
总是可以
uint<M>
到 uint<N>
总是可以
对于其他一切:
- 如果源值在编译时已知,则应该存在编译错误。
- 如果在编译过程中该值未知,请查看转换是否能正常工作,否则抛出异常。
对于情况 (1),使用 constexpr-throw 技巧不起作用:考虑以下(非 constexpr 上下文):
// Will compile, but it shouldn't. Instead of not compiling it will throw an exception.
int<16> foo(12345);
// Will compile. Whatever the type of some_value_from_outside is,
// check that it fits at runtime. If it does not, throw an exception.
int<16> thisIsFine(some_value_from_outside);
理想的是 关于 constexpr 参数的重载解决方案,它不存在,所以我试图找到最好的解决方法。
I want to disable a function for any compile-time evaluated argument
这是不可能的,也没有任何意义(一般来说)。
在实践中,as-if rule, most optimizing compilers will generate the same code for f(2);
and { int i=2; f(i); }
since both have the same semantics。
和GCC and also Clang, you might use __builtin_constant_p
使用 GCC,您可能会花费数周或数月的时间在插件中编写 GCC plugin which would detect (and emit a diagnostic for) calls to function with compile time argument (e.g. you could implement your new function attribute。但这不会改变重载或输入规则。而且我真的不建议在您的特定情况下制作插件。
你的问题还不清楚,看起来你想要一些 C++ 没有提供的东西。顺便说一句,int<16>
不是合法的 C++,因为 int
不是模板。也许你想要 std::int16_t
?
您是否考虑过一些其他方法,也许从其他东西生成 C++ 代码,也许使用其他一些预处理器(例如 GPP or m4) or C++ code generator (your own one, perhaps; Qt moc or GNU bison or SWIG 可能很有启发性)。
我暂时接受,现在可以检查表达式是否为 constexpr,既不是通过重载(可能很有趣),也不是通过任何其他方法。但是,作为参考,我应该在此处列出当前的解决方法:
将常量声明为 constexpr 并使用以下成语
value fits in type ? cast to type : throw CastException
只有当值符合类型时才会编译,否则函数不是 constexpr。
使用另一种模板化工厂方法 c++ compile-time check function arguments。
我会选择 (1),因为它不需要对 constexpr 情况使用不同的语法。另外,我认为无论如何命名常量是一个好习惯。
我想为任何编译时评估的参数(文字,或来自 constexpr 表达式的东西)禁用一个函数。这可能吗?
对于整数,可以使用非类型模板参数执行相反的操作,但这也会改变调用语法。
我正在玩严格的整数,需要以某种方式启动。当前处理错误输入的规则:
如果源值仅在运行时已知,并且缩小转换会破坏解释(而不是位),则会抛出异常
如果源值在编译时已知,但它不适合应该是编译错误。
我的想法是禁用接受所有 constexpr 参数的更宽类型的构造函数。
所谓严格,是指只允许保值转换:
假设 N >= M
int<M>
到int<N>
总是可以uint<M>
到uint<N>
总是可以
对于其他一切:
- 如果源值在编译时已知,则应该存在编译错误。
- 如果在编译过程中该值未知,请查看转换是否能正常工作,否则抛出异常。
对于情况 (1),使用 constexpr-throw 技巧不起作用:考虑以下(非 constexpr 上下文):
// Will compile, but it shouldn't. Instead of not compiling it will throw an exception.
int<16> foo(12345);
// Will compile. Whatever the type of some_value_from_outside is,
// check that it fits at runtime. If it does not, throw an exception.
int<16> thisIsFine(some_value_from_outside);
理想的是 关于 constexpr 参数的重载解决方案,它不存在,所以我试图找到最好的解决方法。
I want to disable a function for any compile-time evaluated argument
这是不可能的,也没有任何意义(一般来说)。
在实践中,as-if rule, most optimizing compilers will generate the same code for f(2);
and { int i=2; f(i); }
since both have the same semantics。
和GCC and also Clang, you might use __builtin_constant_p
使用 GCC,您可能会花费数周或数月的时间在插件中编写 GCC plugin which would detect (and emit a diagnostic for) calls to function with compile time argument (e.g. you could implement your new function attribute。但这不会改变重载或输入规则。而且我真的不建议在您的特定情况下制作插件。
你的问题还不清楚,看起来你想要一些 C++ 没有提供的东西。顺便说一句,int<16>
不是合法的 C++,因为 int
不是模板。也许你想要 std::int16_t
?
您是否考虑过一些其他方法,也许从其他东西生成 C++ 代码,也许使用其他一些预处理器(例如 GPP or m4) or C++ code generator (your own one, perhaps; Qt moc or GNU bison or SWIG 可能很有启发性)。
我暂时接受,现在可以检查表达式是否为 constexpr,既不是通过重载(可能很有趣),也不是通过任何其他方法。但是,作为参考,我应该在此处列出当前的解决方法:
将常量声明为 constexpr 并使用以下成语
value fits in type ? cast to type : throw CastException
只有当值符合类型时才会编译,否则函数不是 constexpr。
使用另一种模板化工厂方法 c++ compile-time check function arguments。
我会选择 (1),因为它不需要对 constexpr 情况使用不同的语法。另外,我认为无论如何命名常量是一个好习惯。