3

template-typedef が利用可能になったので、型を変換するクラスに便利なラッパーを提供する必要があるのではないかと考えていました。この(役に立たない)例を考えてみましょう:

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

ここでstd::conditionaltransform、 で使用されるタイトルからtypename transform<...>::typeです。また、whateverそれ自体もtransform同じように使用されます。

template-typedefs (aka 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 を提供する必要があるかという疑問が残ります。ラッパーを提供する利点の 1 つは、ユーザー エラーを防止できることです。たとえば、この質問と回答を参照してください。

既存のインターフェイスを維持するために、次の点がわかりました。

  • 一貫性。それが型特性であり、基本的に誰もが使用しています
  • 変圧器の分離と変換の結果。上記の場合、トランスフォーマーをタイプとして渡すことができますがwhatever、これはもう不可能です。
  • impl特殊化に必要なソリューションを回避することで、コードを削減します。

「私は 2 番目のアプローチの方が好きだ」という意見だけでなく、「新しい」インターフェースを提供することに賛成または反対する議論を聞きたいと思います。いずれかのアプローチが必要な場合、またはそれが機能/スケーリングに失敗した場合について知りたいです。

正直に言うと、質問は主にテンプレート型定義に関する私の経験不足です。実際の経験があれば、その良い面と悪い面、および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;

私は上記のコードをコンパイルしなかったので、タイプミスをした場合は私を撃たないでください。

利点は、呼び出し元のサイトがはるかに明確になることです。潜在的な欠点の1つは、高階の汎用コードを記述していて、ある型関数内に::typeが存在することに依存している場合です。

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

おそらく、使用ラインをに変更することで逃げることができますが

using apply = F<Ts...>;

害はありません。それはすべて、コードの残りの部分が何をしているかにかかっています。タイプ関数に特定のインターフェイス(::typeまたは::value)が必要な場合は、それらに準拠する必要があります。

于 2013-03-18T14:44:27.467 に答える