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. 如何在build_instances主体中保留numeric_type(如通过 output_iterator 获得它),以便它可以用于一个接一个地构建实例?
  3. 如何确保调用者知道等待包含在 std::unique_ptrs 中的对象?另一种选择就是简单的指针,但我对此并不热情。

有一个类似的问题,标题如何我怎样才能让这个模板方法更优雅?(or: less explicit template parameters required),它接受一个容器并将其转换为不同类型的容器。

编辑 正如对 Jogojapan 的评论所评论的那样,目前我像这样转换输入

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

但是随后的函数调用也需要提供numeric_typetypedef,这有点麻烦。我希望避免这种情况。看起来我错了,但是出于教育和所有目的,是否有可能进一步减少 typedef 数字类型并从迭代器中推断出来的需要?

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别名build_instances将改为

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

最后,我觉得build_instance接受一个T参数但构造some_type<T>. 如果它采用并构造了(其中可能仅限于.)的T实例,那么这也可以避免您的问题。TTsome_type

于 2012-08-15T22:51:35.643 回答