Custom String Literals - c++

Out of curiosity, I was wondering how different files are able to assign certain symbols to change they regular c-string literals into other literals.
For Example...
In Objective-C, the NSString literal can be written by #"..."
In C++ (I think), the C++ String literal is written S"..."
In the wchar library, the wchar_t literal is writtel L"..."
Can anyone tell me how to do a string like, MyClass literal as #"..."
Thanks

You can use only something like this.
#include <iostream>
#include <string>
struct MyClass
{
public:
MyClass(const char* a, size_t sz):
s(a, sz)
{
}
std::string get() const { return s; }
private:
std::string s;
};
MyClass operator "" _M(const char* arr, size_t size) { return MyClass(arr, size); }
int main()
{
MyClass c = "hello"_M;
std::cout << c.get() << std::endl;
}
C++11 allows user-defined literals. http://liveworkspace.org/code/cfff55e34d3b707e1bf0cb714e8e8f29
But there are no abilities to define prefix literals.

Related

initialize vector of structs of string literals in c++

I have an API:
void func(struct s st)
{
//do some stuff
}
when struct s define as:
struct s
{
char* str1;
char* str2;
};
Now, I want to call func() multiple times with different pairs of string literals.
So I wanted store my structs in iterable container. for example std::vector:
const std::vector <struct s> sts=
{
{
"str1",
"str2"
},
{
"str3",
"str4"
}
...
};
for(auto& st : sts)
{
func(st);
}
But I get an error:
ISO C++ forbids converting a string constant to ‘char*’.
I know the problem is that I try to assign string literal (const char*) to char*, but how can I fix it?
I know I can implement init function (or define), and call it every time. something like:
s init_struct(const char* str1, const char* str2)
{
char *str1_ = strdup(str1);
char *str2_ = strdup(str2);
return {str1_, str2_};
}
but I want my code simply as possible. also, I can't change func() prototype or struct s declaration.
My question is: what is the fastest and cleanest way to initialize iterable container with the structs?
When I say "fastest" I don't mean to performance (my code doesn't run in real time), but in terms of readability.
In C++, the type of a string literal is an array of const char. Hence, you should define your structure to take a const char *:
struct s
{
const char* str1;
const char* str2;
};
While it would work to use string, this creates unnecessary copies, since the string literals are not going away. (If you want to use a more C++ type, at least use string_view rather than string, but given how simple this case is, I think const char * is just fine.)
First thing to recognize, you'll need to copy somewhere. On some architectures, cstring literals are in a different kind of memory than char*, so to be standard compliant, you need this.
Second trick, a std::initializer_list<T> can be initialized from a class that descends from T. Thus, you can add a class (scons) that has the proper constructor (and descends from s). While in general you cannot convert container<scons> to container<s>, you can still initialize a vector<s> as it'll look for std::initializer_list<s>, which can be constructed this way. Easier to tell by code:
#include <vector>
#include <string.h>
struct s
{
char* str1;
char* str2;
};
// even this could be templated, as arg count can be deduced using structured binding in c++17
struct scons : s
{
scons(const char* s1, const char* s2)
: s{strdup(s1), strdup(s2)} {}
};
int main() {
std::vector<s> v =
{
scons{
"str1",
"str2"
},
{
"str3",
"str4"
},
{
"str5",
"str6"
}
};
}
Note that you only need to specify the new ctor for the first element, the rest is auto-deduced.
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
struct s
{
char* str1;
char* str2;
s(){
}
s(string s1, string s2){
str1=new char[s1.size()+1];
str1[s1.size()]=0;
for(int i(0);i<s1.size();++i)
str1[i]=s1[i];
str2=new char[s2.size()+1];
str2[s2.size()]=0;
for(int i(0);i<s2.size();++i)
str2[i]=s2[i];
}
};
int main(){
const std::vector <struct s> sts=
{
{
"str1",
"str2"
},
{
"str3",
"str4"
}
};
return 0;
}
Is that ok?

It is possible to pass an empty string literal to a user-defined raw literal operator?

Consider the following simple user-defined raw literal operator:
#include <string>
std::string operator""_s(const char* s) {
return s;
}
which gives us another easier way to generate std::strings with only integer characters:
auto s1 = 012345_s; // s1 is "0123456"s
auto s2 = 0_s; // s2 is "0"s
But is it possible to generate empty string using this raw literal operator?
auto s3 = ???_s; // s3 is ""s
The single-argument form T operator""_s(const char* s) is just a fallback case for integers and floating-point types.
The proper way to handle a user-defined string literal is via T operator""_s(const CharT* s, size_t sz).
#include <string>
std::string operator""_s(const char* s) {
return s;
}
std::string operator""_s(const char* s, size_t sz) {
return {s,sz};
}
int main()
{
auto s1 = 012345_s;
auto s2 = 0_s;
auto s3 = ""_s;
}
https://godbolt.org/z/qYM1WaKrh

Is it possible to create a user defined literal, which converts string literals to an array of own-type?

Is it possible to create a user defined literal, which converts string literals to an array of own type?
Suppose that I have an own byte type, mylib::byte:
namespace mylib {
enum class byte: unsigned char { };
}
So, for example, "Hello"_X should have the type mylib::byte[5], with the value of { 'H', 'e', 'l', 'l', 'o' }.
Here's the background, so maybe you can recommend some other solution.
I have a utf-8 class, which stores a mylib::byte *, and a length (this works like std::string_view, it doesn't own the memory area):
namespace mylib {
class utf8 {
const byte *m_string;
int m_length;
};
}
I'd like to able to construct mylib::utf8 with string literals in the code conveniently, something like this:
mylib::utf8 u = "Hello";
Currently, I use reinterpret_cast, which is UB:
namespace mylib {
class utf8 {
const byte *m_string;
int m_length;
public:
utf8(const byte *s) {
m_string = s;
m_length = ...;
}
utf8(const char *s) {
m_string = reinterpret_cast<const byte *>(s); // causes UB afterwards
m_length = ...;
}
};
}
So I thought, I'd like to have something like this, to avoid UB:
mylib::utf8 u = "Hello"_X; // I'd like to have the constructor with `const byte *` to be called here
Note: using mylib::byte is mandatory, I cannot change it.
mylib::utf8 operator "" _X(const char* c, std::size_t n) {
auto* r = new mylib::byte[n];
std::transform(c, c+n, r, [](auto c){ return (mylib::byte)(unsigned char)(c););
return {r,n};
}
this meets all of your criteria as written; you didn't demand zero leaks.

cannot copy string to an character array

#include<iostream>
class ravi
{
private:
char a[10],char b[10];
public:
void setdata(char x[10],char y[10])
{
a = x; b = y;
}
void show()
{
std::cout << a << b;
}
};
int main()
{
ravi r;
r.setdata("text","copied");
r.show();
}
i am trying to copy the strings "text" "copied" to x and y and i am getting an error that "incompatible types in assignment from char* to char" .can someone tell me what is wrong with my code.
Strings in C++ are std::string. You are using char arrays, aka C-strings, NUL terminated strings, etc. which are harder to manipulate.
Simply by replacing the type of a and b (and a minor improvement on the arguments of setdata, you get something working, plus some useful features of string:
#include <string>
class ravi
{
std::string a;
std::string b;
public:
void setdata(const char* x, const char* y)
{
a = x;
b = y;
}
void show()
{
std::cout << a << b;
}
};
If this is possible (regarding the API of ravi), try and use std::string const& in lieu of const char*:
void setdata(std::string const& x, std::string const& y)
With C++17, you'd better use std::string_view in lieu of const char* for argument types:
void setdata(std::string_view x, std::string_view y)
Arrays do not have the copy assignment operator. So these statements
a=x;b=y;
are invalid.
You should use standard C function strcpy or strncpy declared in the header <cstring> to copy character arrays. Also string literals in C++ have types of constant character arrays. So the parameters of the member function setdata should be declared with the qualifier const.
void setdata( const char x[], const char y[] )
{
strncpy( a, x, sizeof( a ) );
a[sizeof( a ) - 1] = '\0';
strncpy( b, x, sizeof( b ) );
b[sizeof( b ) - 1] = '\0';
}
Take into account that this statement is invalid
char a[10],char b[10];
Either you should write
char a[10]; char b[10];
or
char a[10], b[10];
Use the strcpy function from string.h:
#include <string.h>
void setdata(char x[10],char y[10])
{
strcpy(a,x);
strcpy(b,y);
}

'+' Operator overloading in C++

I just started learning about operator overloading and was just playing around with code to learn how it works. So, I wrote a code that adds two characters. Ex: '#' + '%' = 'H' because of ASCII value addition.
Here is my code:
#include <iostream>
using namespace std;
class Strings {
//everything is public
public:
char str;
//empty constructor
Strings();
Strings(char);
//operator takes in an object of Strings
Strings operator+(Strings);
};
Strings::Strings()
{}
//constructor
Strings::Strings(char a) {
str = a;
}
//aso is "another string object"
//makes new empty object "brandNew"
//brandNew is the two characters added together
//returns object brandNew
Strings Strings::operator+(Strings aso) {
Strings brandNew;
brandNew.str = str + aso.str;
return brandNew;
}
int main() {
Strings a('#');
Strings b('%');
Strings c;
//now, we can use + operator to add characters
c = a + b;
cout << c.str << endl;
return 0;
}
What if I wanted to add two strings? If I make the input
Strings a("###");
Strings b("%%%");
And I want the output to be
HHH
How would I alter my code to add the two strings? I started with changing all of the char type declarations into string. I'm thinking I would have to make a for loop inside the operator function to iterate through each character of both inputs while adding them. But, I'm confused on the syntax for it and also confused on how to implement that. Any help and explanation would be appreciated!
I will give you some help declaring the class.
class Strings {
private:
char* str;
unsigned int length;
unsigned int size;
public:
//constructor
Strings();
~Strings();
Strings(const char*);
Strings(const Strings&);
//operator
Strings operator+(const Strings&);
Strings operator+(const char*);
Strings operator=(const Strings&);
Strings operator=(const char*);
Strings operator+=(const Strings&);
Strings operator+=(const char*);
///Accessors
const char* GetStr()const;
unsigned int GetLength()const;
unsigned int GetSize()const;
};