gpt4 book ai didi

c++ - c++ 元编程中的 typedef 与公共(public)继承

转载 作者:可可西里 更新时间:2023-11-01 16:41:44 34 4
gpt4 key购买 nike

免责声明:问题与Inheritance instead of typedef完全不同到目前为止我找不到任何类似的问题

我喜欢玩 C++ 模板元编程(主要是在家里,我有时会在工作中轻率地介绍它,但我不想让程序只对那些不费心去学习它的人可读),但是我一直每当出现问题时,编译器错误就会完全消除。

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

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

我已经替换了代码中的一些 typedef,并改用了继承。

typedef partition<AnyType> MyArg;

struct MyArg2: partition<AnyType> {};

这并不是要输入更多的字符,在我看来,这也不是不那么易读。事实上,它甚至可能更具可读性,因为它保证声明的新类型靠近左边距,而不是在右侧的未确定偏移处。

然而,这涉及另一个问题。为了确保我没有做任何愚蠢的事情,我经常像这样编写模板函数/类:
template <class T> T& get(partition<T>&);

通过这种方式,我确信只能为合适的对象调用它。

特别是在重载运算符(例如 operator+)时,您需要某种方法来缩小运算符的范围,或者冒着为 int 调用它的风险。

但是,如果这适用于 typedef 的类型,因为它只是一个别名。它肯定不适用于继承......

对于函数,可以简单地使用 CRTP
template <class Derived, class T> partition;

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

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

这个问题的另一个解决方案是在我的类型中添加一个“标签”属性,以将它们彼此区分开,然后依靠 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...*/));
};

我倾向于使用更多的“静态断言”而不是“enable_if”,我认为一段时间后我回来时它更具可读性。

嗯,基本上我还没有下定决心,我仍在尝试这里公开的不同技术。

你使用 typedef 还是继承?
您如何限制方法/函数的范围或以其他方式控制提供给它们(和类)的参数类型?

当然,如果可能的话,我更喜欢个人喜好。如果有使用特定技术的合理理由,我宁愿知道它!

编辑:

我在浏览 stackoverflow 时刚刚从 Boost.MPL 中找到了这个 perl,我完全忘记了:

BOOST_MPL_ASSERT_MSG

这个想法是你给宏 3 个参数:
  • 检查条件
  • 应该用于在错误消息中显示的消息(C++ 标识符)
  • 涉及的类型列表(作为元组)

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

    最佳答案

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

    我没有找到你的推导想法而不是 typedef并使用 enable_if非常吸引人。正如您自己所说的那样,它通常只是为了更好的编译器错误消息而掩盖了实际代码。

    我发现静态断言好多了。它不需要更改实际代码,我们都习惯于在算法中进行断言检查,并且如果我们想了解实际算法,就学会了在精神上跳过它们,它可能会产生更好的错误消息,并且会延续到 C++ 1X 更好,这将有 static_assert (完全带有类设计器提供的错误消息)内置于语言中。 (我怀疑 BOOST_STATIC_ASSERT 只是使用内置的 static_assert 如果可用的话。)

    关于c++ - c++ 元编程中的 typedef 与公共(public)继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1516217/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com