1

この質問にはさらに準備が必要なので、最初にいくつかのコードを提供し、次に正確な質問を提供します

次の型が宣言されていると仮定します

template<typename T>
struct some_type
{
    T t_;
};

そのようなファクトリ関数で構築されます

typedef float numeric_type;
std::vector<std::string> construction_material;
//Push_back of strings in certain form...
std::vector<std::unique_ptr<some_type<numeric_type>> instances;
build_instances(construction_material.begin(), construction_material.end(), back_inserter(instances));

構築関数は次のようなものになります

template<typename input_iterator, typename output_iterator>
output_iterator build_instances(input_iterator begin, input_iterator end, output_iterator out)
{
    for(input_iterator iter = begin; iter != end; ++iter)
    {
        //This won't work, but to illustrate some ideas...
        //build_instance<std::iterator_traits<output_iterator>::value_type>(*iter)
    }

    //[...]

    return *out;
}

template<typename T>
std::unique_ptr<some_type<T>> build_instance(std::string const& material)
{
    static_assert(std::is_floating_point<T>::value == true, "The template type needs to be a floating point type.");

    std::unique_ptr<some_instance<T>> instance(new some_instance<T>());
    //Some processing...

    return instance;
}

次のように、関数を変更してコンテナを返す(またはコンテナタイプをテンプレート化する)ことができることを知っています

template<typename input_iterator, typename T>
std::vector<std::unique_type<T>> build_instances(input_iterator begin, input_iterator end,       
output_iterator out)
{
    //Likewise code to the previous snippets...
    return ...
}

私が解決できなかった問題は次のとおりです。

  1. back_inserterのようなアプローチを使用することは可能ですか、それとも不可能ですか? 発信者にとって最も柔軟であるように見えますか?
  2. インスタンスを1つずつ構築する際に使用できるように、build_instances本体でnumeric_typeを保持する方法(output_iteratorを介して取得する場合と同様)
  3. std::unique_ptrs にラップされたオブジェクトを待機することを呼び出し元が認識していることを確認するにはどうすればよいですか? 代替手段は単純なポインターと同じですが、私はそれについて熱狂的ではありません。

このテンプレート メソッドをよりエレガントにするにはどうすればよいですか?という見出しの同様の種類の質問があります。(または: あまり明示的なテンプレート パラメーターは必要ありません)。コンテナーを受け取り、それを別の種類のコンテナーに変換します。

編集 Jogojapanのコメントにコメントされているように、現在私は入力をそのように変換しています

std::transform(construction_material.begin(), construction_material.end(), std::inserter(instances, instances.begin()), build_instance<numeric_type>);

ただし、後続の関数呼び出しにも typedef を指定する必要がありnumeric_type、これはやや面倒です。私はそれを避けることを望みます。私は間違っていたようですが、教育とすべての目的のために、数値型を型定義してイテレータから推測する必要性をさらに減らすことは可能でしょうか?

4

1 に答える 1

0

侵入的な解決策はsome_type、型パラメーターを公開することです。同じ方法でstd::unique_ptr<T, D>、最初のパラメーターを経由して公開しますelement_type(これは後で必要になります)。

template<typename T>
struct some_type
{
    // give it an appropriate meaningful name
    using value_type = T;
    value_type t_;
};

template<typename input_iterator, typename output_iterator>
output_iterator build_instances(input_iterator begin, input_iterator end, output_iterator out)
{
    using pointer_type = typename std::iterator_traits<output_iterator>::value_type;
    using value_type = typename pointer_type::element_type::value_type;
    return std::transform(begin, end, out, build_instance<value_type>);
}

テンプレートの特殊化の最初のテンプレート パラメータを非侵入的に抽出することもできます。

template<typename T>
struct first;

template<template<typename...> class Template, typename First, typename... Pack>
struct first<Template<First, Pack...>>> {
    using type = First;
};

template<typename T>
using First = typename first<T>::type;

value_typeエイリアス inはbuild_instances代わりに

using value_type = First<typename pointer_type::element_type>;

build_instance最後に、パラメータを取って のTインスタンスを構築するのは少し奇妙だと思いますsome_type<T>。のインスタンスを取得Tして構築した場合T(おそらくTの特殊化に制限されている場合some_type)、これも問題を免れたでしょう。

于 2012-08-15T22:51:35.643 に答える