【发布时间】:2010-10-17 17:11:20
【问题描述】:
我想实现一个 c++ 库,并且像许多其他库一样,我需要从用户那里获取字符串参数并返回字符串。当前标准定义了 std::string 和 std::wstring(我更喜欢 wstring)。理论上我必须两次使用字符串参数实现方法:
虚拟 void foo(std::string &) = 0; // 在内部从先前定义的字符集转换为 unicode 虚拟 void foo(std::wstring &) = 0;C++0x 并没有让生活更轻松,因为我需要 char16_t 和 char32_t:
虚拟 void foo(std::u16string &) = 0; 虚拟 void foo(std::u32string &) = 0;在内部处理这些不同的类型 - 例如将所有类型放入私有向量成员 - 需要转换、包装器......这太可怕了。
另一个问题是,如果用户(或我自己)想要使用自定义分配器或自定义特征类:一切都会产生全新的类型。例如,要为多字节字符集编写自定义 codecvt 特化,标准说我必须引入一个自定义 state_type - 它需要一个自定义 trait 类,这会产生一个新的 std::basic_ifstream 类型 - 这与期望 std 的接口完全不兼容::ifstream& 作为参数。
一种可能的解决方案是将每个库类构建为一个模板,用于管理用户指定的 value_type、traits 和分配器。但这太过分了,并且使抽象基类(接口)变得不可能。
另一种解决方案是只指定 一个 类型(例如 u32string)作为默认值,每个用户都必须使用这种类型传递数据。但是现在考虑一个使用 3 个库的项目,第一个库使用 u32string,第二个库使用 u16string,第三个库 wstring -> HELL。
我真正想要的是将方法声明为 void foo(put_unicode_string_here) - 不引入我自己的 UnicodeString 或 UnicodeStream 类。
【问题讨论】:
-
在您的应用程序中,您应该始终使用 ONE 字符串类(每个都应该使用该类型(上述类型之一))。这是您的内部字符串表示形式。应用程序的接口可能需要多种不同类型的输入,但此输入总是在传递出接口层之前转换为内部字符串表示形式。
-
我不确定您所指的与编解码器有关的内容。编写它们似乎相对简单。有关简单的使用模式,请参见此处:stackoverflow.com/questions/207662/…
-
如果你必须在你的 codecvt 实现中使用 state_type(在你的例子中是 mbstate_t),你会看到你不能使用 mbstate_t 因为它的实现只有你的 c++ 的开发者知道stl。您需要引入自己的 state_type,然后专门为
编写 codecvt。这就是标准告诉您自定义编解码器的内容。 stroustrups 书中描述了从 std::codecvt 派生,但未涵盖必须使用 state_type 的情况。 -
@martin 作为对您的第一条评论的回应:问题是从输入到内部表示的转换。如何在 basic_string
和 std::wstring 之间轻松转换?如何在 basic_ifstream 和 std::wifstream 之间进行转换?请记住,某些方法可能需要对 std::wstring & Co 的引用。这意味着用户(或 lib 开发人员,如果在内部完成转换)必须管理原始对象和转换后的对象(传递给 lib )。 -
@cytrinox:我还是不明白 codecvt 有什么问题。正如我所说,即使您使用状态类型,它也相对简单。也许最好你问一个关于这个主题的问题,这样你就可以得到正确实施它的建议。