【问题标题】:_Generic: multiple types to a single value?_Generic:多个类型到一个值?
【发布时间】:2015-04-26 05:14:08
【问题描述】:

使用 c11 _Generic 有没有办法将多种类型映射到单个值?

例如:

_Generic(e,      \
    A *:    foo_expression, \
    B **:   foo_expression, \
    C:      foo_expression, \
    enum D: bar_expression, \
    void *: bar_expression)

有没有办法对类型进行分组? (这不是表达意图的有效语法)

_Generic(e, \
    A *: B **: C:    foo_expression, \
    enum D: void *:  bar_expression)

我问的原因是 args foobaz 最终可能是大型表达式(不一定可以重构为函数),因此可以避免大量重复会很好。


注意:

如果不支持使用_Generic 的方式,我_可以_ 制作一个可变参数宏将多个参数粘合到一个值...

#define GENERIC_TYPE_GLUE3(answer, arg0, arg1) \
    arg0: answer, arg1: answer
#define GENERIC_TYPE_GLUE4(answer, arg0, arg1, arg2) \
    arg0: answer, arg1: answer, arg2: answer
....

... 有很多这样的宏,然后使用 varargs 包装器来自动使用正确的,请参阅:https://stackoverflow.com/a/24837037/432509

_Generic(e,      \
    GENERIC_TYPE_GLUE(foo_expression, short int, long),
    GENERIC_TYPE_GLUE(bar_expression, float, double))

(参见工作示例:https://gist.github.com/ideasman42/4426f255880ff6a53080

【问题讨论】:

  • 我从来没有真正研究过通用宏是如何工作的,但是如果你为巨大的foobaz 表达式定义了新的宏呢?有什么东西阻止了它的工作吗?
  • 这在大多数情况下都有效,它只是意味着一次性宏的数量可能会成倍增加(并污染名称空间)。我宁愿使用示例宏将多个类型与单个 arg 粘合在一起。

标签: c generics generic-programming c11


【解决方案1】:

不,与switch 类似,没有预见到为_Generic 重新组合多个案例的语法。那么,您的重组宏方法可能是适合您的目的的方法。你可以看看 boost 或我的包 P99 所做的宏元编程,它允许你只拥有一个这样的宏来计算案例。

【讨论】:

    【解决方案2】:

    对于您的用例,您可以使用类型提升规则

    _Generic((e)+0ULL,             \
        unsigned long long:   foo, \
        default:  bar)
    

    如果你有浮点以外的情况,你甚至可以更进一步

    _Generic((e)+0ULL,             \
        unsigned long long:   foo, \
        default: _Generic((e)+0.0L,\
         long double:   bar,       \
         default:  blur))
    

    这假设您的所有表达式e 都具有算术类型。剩下的 default in 将是 _Complex 类型和所有指针类型。

    无论如何,对于您想到的那种用法,您应该进行此类提升,因为编译器当前以不同方式解释 _Generic 的控制表达式。例如,有些人还会认为double const 类型的对象与double 不同。因此,如果您必须区分所有可能的类型限定,这确实会给您提供很多需要考虑的情况。

    【讨论】:

    • 示例中可以使用的事实类型提升与实际问题无关(不是理想示例),编辑示例。
    猜你喜欢
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2018-02-15
    • 2021-12-04
    • 2021-09-18
    • 2021-06-06
    • 2018-02-28
    • 2021-07-13
    相关资源
    最近更新 更多