我有一个功能
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)
答案 0 :(得分: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) { ... }
从使用标题的人的角度来看这是最好的(他们可以立即看到哪些重载可用),但在实现方面需要稍微多做些工作。
答案 1 :(得分: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());
}
string_ref
可以从const char*
和int
创建,没有任何开销,可以轻松提取两者以进一步传递给C函数。
(命名string_ref
为not random。)