【问题标题】:Disable function only for compile-time argument [closed]仅针对编译时参数禁用功能[关闭]
【发布时间】:2018-03-25 12:36:07
【问题描述】:

我想为任何编译时评估的参数(文字或来自 constexpr 表达式的东西)禁用函数。这可能吗?

对于整数,可以使用非类型模板参数做相反的事情,但这也会改变调用语法。

我正在玩弄严格的整数,这需要以某种方式启动。当前处理错误输入的规则:

  • 如果源值仅在运行时已知,并且缩小转换会破坏解释(而不是位),则会引发异常

  • 如果源值在编译时已知,但不适合,则应该出现编译错误。

我的想法是禁用为所有 constexpr 参数接受更广泛类型的构造函数。

严格来说,我的意思是只允许保值转换:

假设 N >= M

  • int<M>int<N> 总是好的
  • uint<M>uint<N> 总是好的

对于其他一切:

  1. 如果源值在编译时已知,则应该存在编译错误。
  2. 如果在编译期间不知道该值,请查看转换是否可以正常工作,否则抛出异常。

对于情况 (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 参数的重载解析,它不存在,所以我正在努力寻找最佳解决方法。

【问题讨论】:

  • 我想说在你明显的需求背后还有另一个问题
  • 您要解决的真正问题是什么。不,不是“仅针对编译时参数禁用函数”的问题,而是您认为解决方案必须是“仅针对编译时参数禁用函数”的真正问题。
  • 请定义严格整数。我猜不出你的意思;或解释(或至少给出一些例子)什么是非严格整数。
  • 即使是最新的编辑也不提供任何minimal reproducible example。我不明白MN 是什么以及它们来自哪里。 int&lt;16&gt; 看起来很奇怪。你是说int16_t 吗?
  • @BasileStarynkevitch 抱歉标记错误。

标签: c++ typetraits


【解决方案1】:

我想为任何编译时评估的参数禁用一个函数

这是不可能的,而且没有任何意义(一般来说)。

实际上,使用as-if rule,大多数optimizing 编译器将为f(2);{ int i=2; f(i); } 生成相同代码,因为它们具有相同的semantics

对于GCCClang,您可以使用__builtin_constant_p

使用 GCC,您可能会花费数周或数月的时间对您的 GCC plugin 进行编码,这将检测(并发出诊断)调用以使用编译时参数(例如,您可以在插件中实现新的 function attribute)。但这不会改变重载或打字规则。而且我真的不建议在您的特定情况下制作插件。

您的问题仍然不清楚,看起来您想要 C++ 不提供的东西。 BTW int&lt;16&gt; 不是合法的 C++,因为 int 不是模板。也许你想要std::int16_t

您是否考虑过其他方法,可能从其他东西生成 C++ 代码,可能使用其他预处理器(例如 GPP 或 m4)或 C++ 代码生成器(可能是您自己的;Qt moc 或 GNU @987654332 @ 或 SWIG 可能会鼓舞人心)。

【讨论】:

  • __buildin_constant_p 不能解决问题,因为您无法将其输入static_assert
  • @BasilieStarynkevitch StackOverflow 理解了这个问题,并建议看看stackoverflow.com/questions/18981752/…,这基本上是我需要做的。
【解决方案2】:

我现在接受这一点,现在可以检查表达式是否为 constexpr,既不是通过重载(可能很有趣),也不是任何其他方法。但是,作为参考,我应该在这里列出当前的解决方法:

  1. 将常量声明为 constexpr 并使用以下成语

    value fits in type ? cast to type : throw CastException
    

    只有当值适合类型时才会编译,否则函数不是 constexpr。

  2. 使用c++ compile-time check function arguments 中提到的替代模板化工厂方法。

我会选择 (1),因为它不需要针对 constexpr 情况使用不同的语法。另外,我认为无论如何命名常量是一个好习惯。

【讨论】:

    猜你喜欢
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多