非构造函数成员函数中的显式字符串行为

时间:2013-01-16 21:15:58

标签: c++

我希望我能正确地提出我的问题。

我有一个非常大/旧的数据库,包含许多非空终止的char数组和一些std :: string类型。我正在创建一个将使用此数据库的工具,我想确保它对于非null终止的char数组是安全的。理想情况下,我希望支持这两种类型,以便开发人员可以轻松使用该工具。

void AddCell( const std::string & _cell_str );
void AddCell( const char * _cell_data, size_t _array_size );

但是,有一个特定的场景可能会出现问题:如果新开发人员不知道char数组是非null终止而且懒惰则决定使用std :: string的隐式转换,因为他没有必须输入数组大小,然后std :: string可能会显示一些不需要的字符。

我该如何处理这个问题?我应该强迫某人指定std :: string的长度吗?我应该只删除std :: string重载函数并让每个人从他们的std :: string中使用c_str()吗?理想情况下,我只使用explicit关键字,但它仅适用于构造函数。我犹豫是否要避免使用std :: string。

2 个答案:

答案 0 :(得分:6)

可以做不同的事情。其中一个是delete - const char*重载:

void AddCell(const std::string&);
void AddCell(const char*) = delete;
void AddCell(const char*,size_t);

将函数标记为delete会在使用时触发编译器错误,但不会将其从过载的候选函数集中删除。如果用户传递const char*,则会拾取第二个重载,并且编译器会尖叫表示重载已被删除。

当然,您还可以为已知大小的数组提供包装器,以便它们可以安全无缝地传递文字:

template <size_t N>
void AddCell(const char (&array)[N]) {
   AddCell(array, N);
}

这允许AddCell("MyCell"),因为文字是一个数组,而最佳候选者是模板,而模板又会以适当的大小调度到(const char*,size_t)重载。

答案 1 :(得分:5)

您可以更改第一个重载,以便不使用std :: string引用,而是引用您创建的具有std :: string隐式转换的新类型。所以你不会看到来自const char *的隐式转换,但是会使std :: string没有问题。