1

我有一个功能

foo(int, int, int, int/long long/_int64/double/long double/char *, int ONLY IF previous char * - otherwise unneeded)

问题是,由于需要字符串副本,char * 实现与值类型不同。是的,这是旧代码的接口,所以我不能使用 std::string :/

目前,我将它作为模板,以及 char * 的函数重载,并带有额外的参数。但是,其他类型的所有操作在 char * 上也是有效的,所以如果调用者忘记了最后一个参数,函数会默默地匹配模板,从而产生错误的逻辑。

有什么方法可以强制在函数模板中使用重载/使用默认参数/允许特定类型使用不同签名(额外参数)而不默默匹配较小签名的东西?

更多:还不能访问 C++11,但我愿意看到使用它来帮助推动采用的建议。没有提升,但和上面一样

我也试过

return_type foo(int,int,int,typename std::enable_if<!std::is_pointer<T>::value, T>::type & value2update)

没有任何运气。然后它声称带有双 & 参数的调用无法匹配。

4

2 回答 2

2

你可以让链接器帮助你。char*在标题中声明但不定义您的函数模板和重载:

template<typename T>
foo(int, int, int, T);
foo(int, int, int, char*, int);

在实现文件 (.cpp/.cc) 中,实现两个:

template<typename T>
foo(int, int, int, T) { ... }

foo(int, int, int, char*, int) { ... }

并显式实例化您想要接受的类型的版本:

template<>
foo(int, int, int, int);
template<>
foo(int, int, int, long long);
// etc.

如果我理解正确,ScottLamb 在评论中提出了类似的建议。标题:

foo(int, int, int, int);
foo(int, int, int, long long);
...
foo(int, int, int, char*, int);

实施文件(.cpp/.cc):

namespace {
    template<typename T>
    foo_tmpl(int, int, int, T) { ... }
}

foo(int, int, int, int) { foo_tmpl(...); }
foo(int, int, int, long long) { foo_tmpl(...); }
....
foo(int, int, int, char*, int) { ... }

从使用标头的人的角度来看,这是更可取的(他们可以立即看到哪些重载可用),但在实现方面需要做更多的工作。

于 2013-03-01T23:52:28.133 回答
1

使用string_ref为您捆绑这两个参数的辅助类:

class string_ref {
  const char *str;
  std::size_t len;
public:
  string_ref(std::string const& s)
    : str(s.c_str()), len(s.size()) {}

  string_ref(const char *c, std::size_t len)
    : str(c), len(len) {}

  const char * c_str() const { return str; }
  std::size_t size() const { return len; }
};

进而

foo(int, int, int, int/long long/_int64/double/long double/const char*, [int])

只需添加

foo(int, int, int, string_ref)
{
   foo(int, int, int, c_str(), size());
}

Astring_ref可以从 a 创建const char*并且int没有开销,并且两者都可以轻松提取以进一步传递给 C 函数。

(命名string_ref不是随机的。)

于 2013-03-01T23:43:53.667 回答