简体   繁体   English

使用模板和字符串?

[英]Using templates and strings?

I have a handy function which splits a string into parts. 我有一个方便的功能,将字符串分成几部分。 The implementation is not important for my question. 实施对我的问题并不重要。

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

I want to make a templated version of this function in order to support wstrings and other kinds of strings. 我想制作这个函数的模板版本,以支持wstrings和其他类型的字符串。 However, if I do this 但是,如果我这样做

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

then it does not work as expected 然后它没有按预期工作

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

My question is why using string constants does not work with the templated version while it works with the untemplated one. 我的问题是为什么使用字符串常量不能与模板化版本一起工作,而它与未模板化的版本一起工作。 My assumption is that in the untemplated case, there is an implicit conversion from char[] to std::string while for templates, the matching occurs before implicit conversion. 我的假设是在未计算的情况下,存在从char[]std::string的隐式转换,而对于模板,匹配发生在隐式转换之前。

How can I remedy the "ambiguity problem"? 如何解决“歧义问题”? Can I maybe make a specialized version of tsplit which does the conversion to std::string and calls tsplit ? 我可以制作一个专门版本的tsplit来转换为std::string并调用tsplit吗?

std::string and const char* are different type, so in std::stringconst char*是不同的类型,所以在

tsplit(str, " ", vec_strPart);

It is ambiguous if you want that StringType is std::string or const char* . 如果你想要StringTypestd::stringconst char* ,那就不明确了。

One way to fix that is to have template for each argument: 解决这个问题的一种方法是为每个参数设置模板:

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

An other way is to deduce only for one parameter, and make some arguments non deducible: 另一种方法是仅推导出一个参数,并使一些参数不可推导:

// 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);

If you declare your function like this 如果你声明你的功能是这样的

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

Then your example compiles. 然后你的例子编译。 The automatic conversion is then deferred to your implementation. 然后,自动转换将推迟到您的实施中。

And so implementation matters ;-) 所以实施很重要;-)

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
}

Out of topic: why return value if you give the third parameter and do you really need template parameter for resulting strings type? 超出主题:为什么返回值,如果你给出第三个参数,你真的需要模板参数的结果字符串类型? Maybe it'd be better to have one of the following: 也许最好有以下其中一种:

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

or 要么

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM