2012-08-15 182 views
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中的对象?另一种选择就像普通的指针一样,但我对此不感兴趣。

对于标题How can I make this template method more elegant? (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_type的typedef过,这是有点麻烦。我希望避免这种情况。 看起来我错了,但为了教育和所有的目的,是否可以进一步减少typedef数字类型的需求并从迭代器中推导出它?

+2

对于问题2,可能类似decltype(*((* it).front()。get()))会起作用吗? – Moritz 2012-08-15 10:30:15

+1

'some_type '的作用/意义是什么?在你的例子中,调用者准备一个'vector >',但是'build_instances()'似乎填充了一个'vector >>,或者我误解了任何东西。另外,在'build_instance()'中,您似乎将类型的名称从'some_type '切换为'some_instance '。 – jogojapan 2012-08-15 12:40:06

+0

@Moritz,我会在一段时间后再回来。 – Veksi 2012-08-15 13:34:23

回答

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并构建了T的实例(其中T限制为some_type的专业化)。这也可以避免你的问题。

+0

我刚醒来,我不得不让它沉入我的片刻。 :-)我在模板上有点绿,所以有些因素会影响我为什么使用T参数。虽然我没有立即看到如何将参数从普通T改为some_type 会使问题消失。我想我想要做的是用户插件,用构造的实例填充一些任意容器,作为参数,而不是返回“预先选定的容器”,比如std :: vector > 。这有点失控,但是再一次,学习是好的! – Veksi 2012-08-16 06:36:02

+0

@Veksi我刚刚意识到我的回答并不完整。 – 2012-08-16 07:32:50

+0

我需要在g ++上测试它,但看起来似乎合理。 VC 2012 RC不支持可变模板... – Veksi 2012-08-18 11:01:37