如何避免泛型函数模板中的额外副本?

时间:2013-02-13 09:46:24

标签: c++ templates c++11

背景

我有一些使用boost::variant存储多种类型的持久性通用代码。在输出值时,我必须编写一个转换器函数protected_backslash_n,它在默认情况下什么都不做,但返回相同的值。

在模板参数为std::string的特殊情况下,我使用boost::regex_replace()搜索\n并将其替换为\\n

问题

代码工作正常,但如果我可以在通用情况下摆脱额外的副本,那将是很好的,因为按值返回

是否有办法在允许专用std::string版本正常工作的情况下执行此操作?

我尝试将返回值更改为T const&,但专用版本不会匹配。

错误

GetPipedValues.hpp:15:21: error: template-id ‘protect_backslash_n<std::string>’ for ‘std::string pitbull::protect_backslash_n(const string&)’ does not match any template declaration

代码

template<typename T>
inline T protect_backslash_n( T const& orig )
{
    return orig;  // BAD: extra copy - how do I get rid of this?
}

template<>
inline std::string protect_backslash_n<std::string>( std::string const& orig )
{
    boost::regex expr("(\\n)");
    std::string  fmt("(\\\\n)");
    return boost::regex_replace(
        orig, expr, fmt, boost::match_default | boost::format_all
    );
}

2 个答案:

答案 0 :(得分:4)

不要把它变成模板,而只是过载。如果参数匹配,编译器将在模板实例化上选择该函数。

std::string protect_backslash_n( std::string const& orig);

答案 1 :(得分:0)

这应该很简单:

  template <typename T>
  T const& protect_backslash_n(T const& orig)
  { 
    return orig; 
  }

std::string版本一样。也许你需要额外的重载,例如采取一个非对象的参考。在C ++ 11中,该函数应该在默认情况下模仿std::forward<T>