有没有办法取消定义chars和wchar_t的字符串和字符串的+ =?
基本上我想避免以下错误:
int age = 27; std::wstring str = std::wstring(L"User's age is: "); str += age; std::string str2 = std::string("User's age is: "); str2 += age;
上面的代码将ascii字符27添加到字符串而不是数字27.
我显然知道如何解决这个问题,但我的问题是:在这种情况下如何产生编译器错误?
注意:您可以在std :: string和int上覆盖+ =以正确格式化字符串,但这不是我想要做的.我想在这些操作数上完全禁止这个操作符.
您无法停用类的特定功能(此处为std :: basic_string),因为它的界面明显(并且正式)允许该操作.试图使操作员超载只会搞砸.
现在,您可以使用私有继承或组合将std :: basic_string"包装"在另一个类中,然后使用公共接口作为std :: basic_string部分的代理,但只使用您希望可用的函数.
我建议先用typedef替换你的字符串类型:
namespace myapp { typedef std::string String; typedef std::wstring UTFString; }
然后,一旦你的应用程序在用myapp :: String和myapp :: UTFString(那些是示例名称)替换std :: string和std :: wstring之后编译正常,你可以在某处定义包装类:
namespace myapp { /** std::basic_string with limited and controlled interface. */ template< class _Elem, class _Traits, class _Ax > class limited_string { public: typedef std::basic_string< _Elem , _Traits, _Ax > _String; // this is for easier writing typedef limited_string< _Elem, _Traits, _Ax > _MyType; // this is for easier writing private: _String m_string; // here the real std::basic_string object that will do all the real work! public: // constructor proxies... (note that those ones are not complete, it should be exactly the same as the original std::basic_string // see some STL docs to get the real interface to rewrite) limited_string() : m_string {} limited_string( const _MyType& l_string ) : m_string( l_string.m_string ) {} limited_string( const _Elem* raw_string ) : m_string( raw_string ) {} //... etc... // operator proxies... _MyType& operator= ( const _MyType& l_string ) { m_string = l_string.m_string; } // etc... // but we don't want the operator += with int values so we DON'T WRITE IT! // other function proxies... size_t size() const { return m_string.size(); } // simply forward the call to the real string! // etc...you know what i mean... // to work automatically with other STL algorithm and functions we add automatic conversion functions: operator const _Elem*() const { return m_string.c_str(); } // etc.. }; }
...然后,您只需替换这些行:
// instead of those lines... //typedef std::string String; //typedef std::wstring UTFString; // use those ones typedef limited_string< char, std::char_traits, std::allocator > String; // like std::string typedef typedef limited_string< wchar_t, std::char_traits , std::allocator > UTFString; // like std::wstring typedef
...而你的例子会崩溃:
error C2676: binary '+=' : 'myapp::UTFString' does not define this operator or a conversion to a type acceptable to the predefined operator error C2676: binary '+=' : 'myapp::String' does not define this operator or a conversion to a type acceptable to the predefined operator
这是我编写的完整测试应用程序代码,用于证明(在vc9上编译):
#include#include namespace myapp { /** std::basic_string with limited and controlled interface. */ template< class _Elem, class _Traits, class _Ax > class limited_string { public: typedef std::basic_string< _Elem , _Traits, _Ax > _String; // this is for easier writing typedef limited_string< _Elem, _Traits, _Ax > _MyType; // this is for easier writing private: _String m_string; // here the real std::basic_string object that will do all the real work! public: // constructor proxies... (note that those ones are not complete, it should be exactly the same as the original std::basic_string // see some STL docs to get the real interface to rewrite) limited_string() : m_string {} limited_string( const _MyType& l_string ) : m_string( l_string.m_string ) {} limited_string( const _Elem* raw_string ) : m_string( raw_string ) {} //... etc... // operator proxies... _MyType& operator= ( const _MyType& l_string ) { m_string = l_string.m_string; } // etc... // but we don't want the operator += with int values so we DON'T WRITE IT! // other function proxies... size_t size() const { return m_string.size(); } // simply forward the call to the real string! // etc...you know what i mean... // to work automatically with other STL algorithm and functions we add automatic conversion functions: operator const _Elem*() const { return m_string.c_str(); } // etc.. }; // instead of those lines... //typedef std::string String; //typedef std::wstring UTFString; // use those ones typedef limited_string< char, std::char_traits , std::allocator > String; // like std::string typedef typedef limited_string< wchar_t, std::char_traits , std::allocator > UTFString; // like std::wstring typedef } int main() { using namespace myapp; int age = 27; UTFString str = UTFString(L"User's age is: "); str += age; // compilation error! std::wcout << str << std::endl; String str2 = String("User's age is: "); str2 += age; // compilation error! std::cout << str2 << std::endl; std::cin.ignore(); return 0; }
我认为它会干净地解决你的问题,但你必须包装所有的功能.
大多数源代码控制系统允许您在签入期间对代码运行健全性检查.因此,您可以设置测试以执行验证并拒绝签入失败:
例:
测试脚本:
#!/bin/tcsh # Pass the file to test as the first argument. echo "#include\ void operator+=(std::string const& , int const&);\ void operator+=(std::string const& , int);"\ | cat - $1 \ | g++ -c -x c++ - >& /dev/null echo $status
该脚本伪造了上面两个运算符的添加(实际上没有改变源).即使原始代码编译,这也会导致使用operator + with strings和char失败.
NB:运营商+ =从litb窃取的想法.谁已经删除了他的例子.但信用到期.