代码之家  ›  专栏  ›  技术社区  ›  Matthieu M.

c++元编程中typedef与公共继承

  •  10
  • Matthieu M.  · 技术社区  · 16 年前

    Inheritance instead of typedef

    问题是,当然,c++模板元编程是基于模板的,因此,当你在深度嵌套的模板结构中遇到编译器错误时,你必须在10行错误消息中挖掘。我甚至养成了在文本编辑器中复制/粘贴消息的习惯,然后缩进消息以获得一些结构,直到我了解实际发生的情况,这为跟踪错误本身增加了一些工作。

    据我所知,问题主要是由于编译器及其输出typedef的方式造成的(还有其他问题,如嵌套深度,但这并不是编译器的错)。即将到来的C++0x宣布了可变模板或类型推断(自动)等很酷的功能,但我真的希望有更好的错误消息来引导。使用模板元编程可能会很痛苦,我确实想知道当更多的人真正开始使用它们时,这会变成什么样子。

    typedef partition<AnyType> MyArg;
    
    struct MyArg2: partition<AnyType> {};
    

    然而,这涉及到另一个问题。为了确保我没有做任何愚蠢的事情,我经常这样编写我的模板函数/类:

    template <class T> T& get(partition<T>&);
    

    CRTP

    template <class Derived, class T> partition;
    
    template <class Derived, class T> T& get(partition<Derived,T>&);
    

    这允许知道在编译器使用公共继承之前用于调用方法的“真实”类型。应该注意的是,这降低了调用此特定函数的机会,因为编译器必须执行转换,但到目前为止,我从未注意到任何问题。

    SFINAE .

    struct partition_tag {};
    
    template <class T> struct partition { typedef partition_tag tag; ... };
    
    template <class T>
    typename boost::enable_if<
      boost::same_type<
        typename T::tag,
        partition_tag
      >,
      T&
    >::type
    get(T&)
    {
      ...
    }
    

    不过,它需要更多的键入,特别是如果在不同的地方声明和定义函数/方法(如果我不费心,我的接口很快就会变得混乱)。然而,当涉及到类时,由于没有执行类型转换,它确实变得更加复杂:

    template <class T>
    class MyClass { /* stuff */ };
    
    // Use of boost::enable_if
    
    template <class T, class Enable = void>
    class MyClass { /* empty */ };
    
    template <class T>
    class MyClass <
      T,
      boost::enable_if<
        boost::same_type<
          typename T::tag,
          partition_tag
        >
      >
    >
    {
      /* useful stuff here */
    };
    
    // OR use of the static assert
    
    template <class T>
    class MyClass
    {
      BOOST_STATIC_ASSERT((/*this comparison of tags...*/));
    };
    

    你如何限制方法/函数的范围,或者以其他方式控制提供给它们(以及类)的参数的类型?

    编辑:

    BOOST_MPL_ASSERT_MSG

    它可能对代码自我文档和更好的错误输出都有很大帮助。

    1 回复  |  直到 9 年前
        1
  •  4
  •   sbi    14 年前

    您要做的是显式检查作为模板参数传递的类型是否提供了必要的概念。除了概念特性,它被C++0X抛弃了(因此是它成为C++1X的主要罪魁祸首之一),当然很难进行适当的概念检查。自90年代以来,已经有几次尝试在没有语言支持的情况下创建概念检查库,但基本上,所有这些都是为了表明,为了正确地做到这一点,概念需要成为核心语言的一个功能,而不是一个仅包含库的功能。

    typedef enable_if 非常吸引人。正如您自己所说,它通常只是为了更好的编译器错误消息而掩盖实际代码。

    static_assert (完全由类设计器提供错误消息)内置到语言中。(我怀疑 BOOST_STATIC_ASSERT 只需使用内置 静态断言 如果可以的话)