2012-08-15 103 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