2016-03-15 40 views
3

我有一個方便的功能,將字符串拆分爲多個部分。實施對我的問題並不重要。使用模板和字符串?

inline std::vector<std::string> & split(const std::string & strInput, const std::string & strPattern, std::vector<std::string> & vec_strPart) 
    {...} 

我想使這個功能的模板化版本,以支持wstrings和其他類型的字符串。但是,如果我這樣做

template <class StringType> 
inline std::vector<StringType> & tsplit(const StringType & strInput, const StringType & strPattern, std::vector<StringType> & vec_strPart) 
    {...} 

那麼它不能如預期般

const std::string str("bla bla blaaaa"); 
const std::string strPattern(" "); 
std::vector<std::string> vec_strPart; 

split(str, strPattern, vec_strPart); // works 
tsplit(str, strPattern, vec_strPart); // works 
split(str, " ", vec_strPart); // works 
tsplit(str, " ", vec_strPart); // does not work, StringType is ambiguous 
tsplit(str, std::string(" "), vec_strPart); // works but changes client's code 

我的問題是,爲什麼使用字符串常量,而它與untemplated一個工作不與模板版本攜手。我的假設是,在未模糊的情況下,存在從char[]std::string的隱式轉換,而對於模板,匹配發生在隱式轉換之前。

我該如何彌補「模糊性問題」?我是否可以製作tsplit的專用版本,該版本的轉換爲std::string,並調用tsplit

+0

也許你可以檢查拆分方法中變量的類型(如果不允許修改客戶端代碼)。看看:http://en.cppreference.com/w/cpp/language/typeid – asalic

回答

3

std::stringconst char*是不同的類型,所以在

tsplit(str, " ", vec_strPart); 

,如果你想它是曖昧StringTypestd::stringconst char*。要解決這個問題

一種方法是有模板爲每一個參數:

template <typename String, typename InputString, typename PatternString> 
std::vector<String>& tsplit(const InputString & input, 
          const PatternString& pattern, 
          std::vector<String>& res); 

的另一種方式是隻推導出一個參數,並提出一些論點非抵扣:

// Helper 
template <typename T> struct non_deducible { using type = t; }; 
template <typename T> using non_deducible_t = typename non_deducible<T>::type; 

template <typename String> 
std::vector<String>& tsplit(const non_deducible_t<String>& input, 
          const non_deducible_t<String>& pattern, 
          std::vector<String>& res); 
+0

這是C++ 03還是C++ 11? – Fabian

+0

可以在C++ 03來完成,通過'的typedef噸型取代'使用類型= t';',並刪除'non_deducible_t'的定義和由'類型名稱non_deducible :: type'取代'non_deducible_t '。 – Jarod42

+1

尼斯招用非抵扣。實際回答OP的問題也是+1。 –

2

如果你聲明這樣

template <class StringType, class TextTypeA, class TextTypeB> 
inline std::vector<StringType> & tsplit(TextTypeA strInput, TextTypeB strPattern, std::vector<StringType> & vec_strPart) 
{ 
... 
} 

你的函數,那麼你的榜樣編譯。自動轉換然後推遲到您的實施。

所以執行的事項;-)

+0

然後我需要在實施的開始時明確轉換嗎?像這樣'const StringType strInputInternal(strInput); const StringType strPatternInternal(strPattern);'另一個問題:你有一個特殊的原因使用值調用,而不是通過調用? – Fabian

+0

顯式轉換可能是一個簡單的解決方案,但也可以使用其他選項。轉換可以自動沿着線路進行。例如,如果您使用find_if明確地使用StringType來避免歧義。 – marom

+0

關於通過電話值一個const裁判可能是更好的,你是對的。但必須經過測試。 – marom

0
template < 
    typename StringType, 
    typename PatternStringType, 
    typename ResultsStringType> 

inline std::vector<ResultsStringType>& tsplit(
    const StringType& strInput, 
    const PatternStringType& strPattern, 
    std::vector<ResultsStringType>& vec_strPart) 
{ 
    return vec_strPart; // your implementation 
} 

出的話題:爲什麼返回值,如果你給第三個參數,做你真正需要的結果字符串類型模板參數?也許最好能夠具備以下條件之一:

template <typename StringType, typename PatternStringType> 
inline std::vector<StringType> tsplit(const StringType& strInput, const PatternStringType& strPattern) 
{ 
    return std::vector<StringType>(); // your implementation 
} 

template <typename StringType, typename PatternStringType> 
inline void tsplit(const StringType& strInput, const PatternStringType& strPattern, std::vector<StringType>& resultingStrs) 
{ 
    // your implementation 
}