模板函数中基于类型的默认参数值

5

假设我有这个函数来修剪std::string,并决定将其扩展,使其不仅从开头和结尾删除空格,还可以从另一个字符串中传递的任何字符,例如空格、换行符和回车符。

std::string Trim ( const std::string &In_Original,
  const std::string &In_CharsToTrim = " \n\r" );

基本上,它会从In_Original的开头和结尾删除所有出现在In_CharsToTrim中的字符。

现在,我不得不为std::string和std::wstring两种类型分别编写此代码。由于我认为这很荒谬,因此我选择使用模板,并且它能正常工作,但是我无法传递默认值,因为std :: wstring版本必须将L" \n\r"作为默认值(请注意那个小写字母L)。

我尝试过这样:

template <typename Type> Type Trim ( const Type &In_String,
  const Type &In_TrimCharacters );

随着:

template std::string Trim ( const  std::string &In_String,
  const  std::string &In_TrimCharacters = " \n\r" );
template std::wstring Trim ( const  std::wstring &In_String,
  const  std::wstring &In_TrimCharacters = L" \n\r" );

但是它没有生效,甚至无法编译。
目前,我所拥有的是一个单独的函数,用于在没有第二个参数时调用,但这完全是错误的方法。
template <typename Type> Type Trim ( const Type &In_String,
  const Type &In_TrimCharacters );
std::string Trim ( const std::string &In_String );
std::wstring Trim ( const std::wstring &In_String );

然后,在这个更简单的Trim函数中,我只是调用了完整版本。
因此,基本上我的问题是这样的:
如何根据模板类型传递不同的默认值?基本上是一种特化,其中唯一的变化是默认参数...
在这种情况下,分别传递std::string(“\n \r”)和std::wstring(L“\n \r”)。
或者......还有其他方法可以实现我在这里尝试做的事情吗?
3个回答

5
这是我想出来的内容:
template <typename T> struct default_trim_chars;

template<> struct default_trim_chars<std::string> { 
    static const char* value() { return " \n\r"; }
};

template<> struct default_trim_chars<std::wstring> { 
    static const wchar_t* value() { return L" \n\r"; }
};

template <typename Type> Type Trim ( const Type &In_String,
const Type &In_TrimCharacters = default_trim_chars<Type>::value()){
    /* ... */
}

您还可以将value声明为数据成员,而不是函数,但这需要使用constexpr和C++11。


这个解决方案在不改变编译器选项的情况下成功运行了,这是必须的。谢谢! - Joao Pincho

3
您可以使用一个简单的 trait 类,将其 ::value 用作默认参数。
template<typename T>
struct type_sensitive_default_argument;

template<>
struct type_sensitive_default_argument<std::string>
{
     static constexpr char value[] = "\n\r";
};

template<>
struct type_sensitive_default_argument<std::wstring>
{
    static constexpr wchar_t value[] = L"\n\r";
};

然后你可以这样做:
template<class Type,
         class Default = type_sensitive_default_argument<Type>>
Type Trim(const Type& In_String,
          const Type& In_TrimCharacters = Default::value);

由于某种原因,我无法编译那段代码。它无法识别constexpr。我将其替换为简单的const,当然,它抱怨我在类声明内初始化了一个const成员变量。所以我删除了初始化,并将其放在声明外面,然后我遇到了难题。我得到了这个错误:error: default template arguments may not be used in function templates without -std=c++11 or -std=gnu++11。 - Joao Pincho
我猜以上所有的错误都是因为我仍在使用C99...真倒霉。我会尝试看看有什么区别,看看是否可以更改编译器设置,而不会有太多麻烦。 - Joao Pincho

1
在您的情况下,您可以依靠指定字符的初始化列表来为您进行转换:
template <typename Type> Type Trim ( const Type &In_String,
  const Type &In_TrimCharacters = { ' ', '\r', '\n' } )
{
    // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接