【问题标题】:C++ Idiomatic Type TraitsC++ 惯用类型特征
【发布时间】:2011-07-04 15:05:20
【问题描述】:

我有一个位于命名空间中的类型特征系统,如下所示:

namespace my_namespace
{

template <typename T>
struct magic_traits
{
    static const int value = 0;
};

}

因为人们讨厌模板特化的语法,所以我有这个方便的小宏:

#define DECLARE_MY_MAGIC_TRAITS(type_, value_) \
    namespace my_namespace                     \
    {                                          \
        template <>                            \
        struct magic_traits<type_ > {          \
            static const int value = value_;   \
        };                                     \
    }

}

我的问题是这只适用于全局命名空间中的声明,因此其他命名空间中的类型的特征如下所示:

DECLARE_MAGIC_TRAITS(other_namespace::some_type, 9)

如果人们知道关于DECLARE_MAGIC_TRAITS 所属位置的所有命名空间小规则,那就太好了。如果他们不这样做并将声明放在他们自己的命名空间中,他们将收到如下错误:

'magic_traits' is not a template!
Specialization of non-template 'other_namespace::my_namespace::magic_traits'

这会让您图书馆的新用户感到困惑!

有没有办法让该宏能够从任何地方定义 magic_traits 的特化? 如果这不可能(我怀疑):可以使用哪些技术生成更合理的错误消息?

我应该注意到,我的用户大多是 Python 程序员,并且几乎没有 C++ 经验,所以我可以做任何事情来让他们的生活更轻松、更好。

【问题讨论】:

  • 如果他们正在编写 C++,那么让他们的生活更轻松的最好办法就是让他们学习 C++。
  • 您想要一个“关闭所有打开的命名空间、执行操作并重新打开所有命名空间”的宏?
  • @Martinho:确实。但是你必须学习大量的 C++ 才能理解 WTF 类型特征的作用,以及相应的语法是什么意思!
  • @Oli:但通常你不应该被要求定义新的类型特征,除非你对你的项目和语言相当熟悉——切向的用户不应该需要我想必须添加特征。
  • @Oli:老实说,我不认为让他们在不知道 WTF 的情况下使用类型特征会更好。

标签: c++ typetraits


【解决方案1】:

也许有点难看,但作为一个想法怎么样:

namespace my_namespace
{

typedef bool The_DECLARE_MY_MAGIC_TRAITS_macro_should_be_used_in_the_global_namespace;

template <typename T>
struct magic_traits
{
    static const int value = 0;
};

}

#define DECLARE_MY_MAGIC_TRAITS(type_, value_) \
    namespace my_namespace {                   \
        typedef The_DECLARE_MY_MAGIC_TRAITS_macro_should_be_used_in_the_global_namespace CheckPrecondition; \
        template <>                            \
        struct magic_traits<type_ > {          \
            static const int value = value_;   \
        };                                     \
    }

宏使用不当会产生如下错误:

error: ‘The_DECLARE_MY_MAGIC_TRAITS_macro_should_be_used_in_the_global_namespace’ does not name a type
error: ‘magic_traits’ is not a template
error: explicit specialization of non-template ‘other_namespace::my_namespace::magic_traits’

这可能足以说明问题所在。

【讨论】:

  • 这里的问题是多重声明问题:如果在单个编译单元中有多个DECLARE_MY_MAGIC_TRAITS,则CheckPrecondition 将已经被定义。这可以通过一些BOOST_PP_COUNTER 魔法来解决。
  • @Travis :也许我误解了你,但与 C 不同的是,在 C++ 中,相同的 typedef 在同一范围内多次出现是完全有效的。或者用标准的话来说:在给定的非类范围内,typedef 说明符可用于重新定义在该范围内声明的任何类型的名称,以引用它已经引用的类型。
  • 哈哈,你说得对。多种语言之间的愚蠢切换让我一团糟。
  • @Travis :虽然不确定我是否真的会在生产代码中使用这种建议的方法......这是模板元编程的一个很好的“技巧”,但也许它应该留在那个利基市场嘿。我同意其他人提到的用户教育可能是要走的路(通过文档、C++ 课程......)
【解决方案2】:

没有什么比好的文档更好的了。

您应该告诉 DECLARE_MAGIC_TRAITS 宏的用户将宏放在哪里,以及在参数中写入什么(带有示例)

并将错误消息设置为常见问题解答条目,以便用户找到问题的正确答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-03
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 2014-06-10
    相关资源
    最近更新 更多