3

我想知道随着模板类型定义的可用性,我应该为转换类型的类提供方便的包装器。考虑这个(无用的)示例:

template< T >
struct whatever
{
   typedef typename std::conditional< sizeof(T) <= sizeof(void*),
                                      int, long >::type type;
};

这里,std::conditional来自transform标题,与 . 一起使用typename transform<...>::type。此外,whatever它本身也是 atransform并以相同的方式使用。

随着模板类型定义(又名using)的可用性,我可以将接口更改为:

template< T >
using whatever = typename std::conditional< sizeof(T) <= sizeof(void*),
                                            int, long >::type;

这简化了使用。对于所有这些情况都可以这样做,但是由于需要(部分)专业化,您有时会得到一个实现类和一个包装器。如果是std::conditional,您可能最终会将其移至std::impl::conditional<...>并提供另一个包装器作为

namespace std
{
  namespace impl
  {
    // "classic" implementation of std::conditional
  }

  template< bool B, typename T, typename F >
  using conditional = typename impl::conditional< B, T, F >::type;
}

这就留下了我应该提供什么接口/API 的问题。我看到了提供包装器的一个优点:它可以防止用户错误。例如,请参阅问题和答案。

为了保留现有界面,我看到以下几点:

  • 一致性。这就是类型特征,基本上每个人都在使用
  • 分离变压器和变换的结果。您可以将变压器作为类型传递,在whatever上述情况下,这将不再可能。
  • 通过防止impl专业化所需的解决方案减少代码。

我想听听支持或反对提供“新”界面的论点,而不仅仅是“我更喜欢第二种方法”之类的意见。我有兴趣找出需要一种或另一种方法或它无法工作/扩展的情况。

老实说,问题主要是我缺乏模板类型定义的经验,所以如果你确实有一些实际经验,请分享它的好与坏,以及我是否应该将typename transform<...>::typeAPI 视为过时的C++11 与否。

4

1 回答 1

0

我总是做以下事情:

  1. 在某些命名空间(impl、detail 等)内部有做实际工作的类。
  2. 在外面,有模板别名来清理调用代码。

例如,如果我要重写 std::remove_reference,我会这样做:

namespace detail {
    template <typename T> struct remove_reference
    {
        using type = T;
    };
    template <typename T> struct remove_reference<T&>
    {
        using type = T;
    };
    template <typename T> struct remove_reference<T&&>
    {
        using type = T;
    };
}

template <typename T>
using remove_reference = typename detail::remove_reference<T>::type;

我没有编译上面的代码,所以如果我打错了请不要拍我。

一个好处是调用站点更加清晰。一个潜在的缺点是,如果您正在编写更高阶的通用代码并依赖于某个类型函数内部存在 ::type,例如

template <template <typename...> class F, typename... Ts>
using apply = typename F<Ts...>::type;

尽管您可能可以将 using 行更改为

using apply = F<Ts...>;

没有任何伤害。这一切都归结为您的其余代码正在做什么。如果您的类型函数需要具有特定接口(::type 或 ::value),那么您需要遵守它们。

于 2013-03-18T14:44:27.467 回答