How to implement typed strings in C ++ 11?

In my project there are many lines with different values ​​in the same area, for example:

std::string function_name = "name"; std::string hash = "0x123456"; std::string flag = "--configure"; 

I want to distinguish different lines by their value, use with function overloads:

 void Process(const std::string& string_type1); void Process(const std::string& string_type2); 

Obviously, I have to use different types:

 void Process(const StringType1& string); void Process(const StringType2& string); 

But how to implement these types in an elegant manner? All I can do is the following:

 class StringType1 { std::string str_; public: explicit StringType1(const std::string& str) : str_(str) {} std::string& toString() { return str_; } }; // Same thing with StringType2, etc. 

Can you recommend a more convenient way?


It makes no sense to rename functions, since the main goal is not to erroneously pass one type of string instead of another:

 void ProcessType1(const std::string str); void ProcessType2(const std::string str); std::string str1, str2, str3; // What should I pass where?.. 
+6
source share
5 answers

You probably need a template with a tag parameter:

 template<class Tag> struct MyString { std::string data; }; struct FunctionName; MyString<FunctionName> function_name; 
+6
source

Simple approach:

 struct flag { string value; }; struct name { string value; }; 

You can improve this by using implicit conversions to strings or other member functions.

+2
source

You can use a similar technique as I applied to std::vector in this answer .

This is how it would look for std::string :

 #include <iostream> #include <string> template<typename Tag, class T> struct allocator_wrapper : T { using T::T; }; template< typename Tag, typename CharT = char, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT> > using MyString = std::basic_string<CharT,Traits,allocator_wrapper<Tag, Allocator>>; class HashTag; class FlagsTag; using Hash = MyString<HashTag>; using Flags = MyString<FlagsTag>; void foo( Hash ) {} int main() { Hash hash( "12345" ); Flags flags( "--foo" ); foo( hash ); // that fine // you can already use them like strings in *some* contexts std::cout << hash << " - " << flags << std::endl; std::cout << ( hash == "12345" ) << std::endl; // but they are not compatible types: // won't compile: // foo( flags ); // std::cout << ( hash == flags ) << std::endl; } 
+2
source

The design you are aiming for is inheritance, as in the other answer here (*). But you should not inherit from std :: string. You can find a lot of discussion about this, for example: Inheriting and overriding std :: string functions? .

This leaves you with your first idea, actually realizing the concept of composition.

(*) I would comment on this answer instead of opening a new answer, but I cannot comment.

+1
source

It all sounds a little bass. You want to have the same name for several functions that do different things for different objects. This is rather strange because the typical approach is to have the same name for functions that perform different things.

Do not skip the “wrong things” is heavily dependent on the programmer, you must remember what you are doing and why. And to test your code when you write it, and you have tests that you run regularly to avoid regressions.

Another approach is to have a set of classes that contain your data and have a common interface, for example:

 class OptionBase { public: OptionBase(const std::string &s) : str(s) {} virtual void Process() = 0; virtual std::string Value() { return str; } virtual ~OptionBase() {} protected: std::string str; }; class FlagOption: public OptionBase { public: FlagOption(const std::string& s) : OptionBase(s) {} void Process() override { ... do stuff here ... } }; class HashOption: public OptionBase { public: HashOption(const std::string& s) : OptionBase(s) {} void Process() override { ... do has stuff here ... } }; class FunctionName: public OptoonBase { ... you get the idea ... }; 

Now you can “handle” all your OptionBase consistent way by calling the same processing function for each of them. But I'm not sure what you were looking for.

0
source

Source: https://habr.com/ru/post/977580/


All Articles