initialize a string size during declaration - c++11

suppose I have a class like this and I would like to create a string with a
specific capacity. I tried doing the following but that did not work.
Any suggestions ? I know I could do it in the constructor but would like to do it during the declaration if possible.
class foo
{
std::string bar = std::string().resize(45);
}
I get the error
main.cpp: In function 'int main()':
main.cpp:8:46: error: conversion from 'void' to non-scalar type 'std::__cxx11::string {aka std::__cxx11::basic_string}' requested
std::string test = std::string().resize(45);

In C++, you probably don't want to "chain" methods unless previous methods have the correct return type.
As suggested by #James Maa, you can do simply use the constructor.

In c++11 we have new feature called move constructor so
string str = string();
doesn't cause extra time.
http://en.cppreference.com/w/cpp/language/move_constructor
with move constructor, the program would directly use the address of the temporary constructed string after = sign, without making a copy.
The problem is that resize()function in c++ actually returns void
basic_string( size_type count,
CharT ch,
const Allocator& alloc = Allocator() );
This constructor might be something you are directly interested in.
You can do something with
std::string str(45, ' ');

Related

Remove class member type part from decltype

I ran into I case I had not seen before, while using decltype on a member of a templated class. I wanted to make a nicer make_unique so that changing type on the member does not cause fixing the make_unique calls. I wanted to avoid this using decltype(member)::element_type as the type for make_unique but got an error. Here is a simple snippet that shows the error (and I understand why it is shown):
#include <memory>
template<typename T>
struct foo
{
foo()
{
// g++ gives:
// dependent-name 'decltype (((foo<T>*)this)->foo<T>::p_)::element_type' is parsed as a non-type, but instantiation yields a type
// say 'typename decltype (((foo<T>*)this)->foo<T>::p_)::element_type' if a type is meant
//
// How can I atleast remove the class name from the type?
p_ = std::make_unique<decltype(p_)::element_type>();
// g++ gives:
// dependent-name 'decltype (p)::element_type' is parsed as a non-type, but instantiation yields a type
// say 'typename decltype (p)::element_type' if a type is meant
//
// makes sense since p here is dependent on T
std::unique_ptr<T> p = std::make_unique<decltype(p)::element_type>();
// This one is fine, makes sense, since the type is known
std::unique_ptr<int> p2 = std::make_unique<decltype(p2)::element_type>();
}
std::unique_ptr<T> p_;
};
int main()
{
foo<int> f;
return 0;
}
My question is, is there a nice/pretty way to remove the 'is a member of' ((foo<T>*)this)->foo<T>::p_))part from the decltype value, so that at least I could use the same fix and simply provide typename on the member variable p_ ? The long fix suggested by g++ seems kind of ugly.
5 minutes after posting I had an idea that I could do
p_ = std::make_unique<decltype(std::remove_reference(*p_)::type)>();
but that seems to give a parse error.
You can simply place a typename before decltype().
I mean
p_ = std::make_unique<typename decltype(p_)::element_type>();

Specialized template accepting constructor parameter when only default constructor defined

So, I have this template class and its specialization.
#include <iostream>
using namespace std;
template<bool> struct CompileTimeChecker{
CompileTimeChecker(...); //constructor, can accept any number of parameters;
};
//specialized template definition
template<> struct CompileTimeChecker<false> {
//default constructor, body empty
};
Case 1:
In the main function I am defining a local class called ErrorA. When I create a temporary of CompileTimeChecker<false> with temporary object of ErrorA fed as an initializer, the compiler is not detecting any error.
int main()
{
class ErrorA {};
CompileTimeChecker<false>(ErrorA()); //Case 1;
CompileTimeChecker<false>(int()); //Case 2;
return 0;
}
Case 2:
Next I feed it with temporary object of type int, and suddenly the compiler recognizes the issue (there is no constructor that takes args in the specialized template CompileTimeChecker<false>)
main.cpp:30:36: error: no matching function for call to ‘CompileTimeChecker::CompileTimeChecker(int)’ CompileTimeChecker<false>(int());
main.cpp:21:23: note: candidate: constexpr CompileTimeChecker::CompileTimeChecker()
template<> struct CompileTimeChecker<false> {
^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:21:23: note: candidate expects 0 arguments, 1 provided
Why does it not recognize the issue in case 1?
CompileTimeChecker<false>(ErrorA());
does not create a temporary of type CompileTimeChecker<false>, passing a temporary ErrorA() to its constructor. Rather, it declares a function named ErrorA, taking no parameters and returning CompileTimeChecker<false> . See also: most vexing parse.
On the other hand, CompileTimeChecker<false>(int()); cannot be parsed as a declaration, so it does unambiguously create a temporary of type CompileTimeChecker<false>.
The easiest way out is to use braces in place of parens to indicate initialization:
CompileTimeChecker<false>{ErrorA{}};

Assigning a string reference to a pointer

I've been stuck on this one problem all day and maybe someone can explain it to me? I'm not providing my exact code, but a similar situation of what I'm trying to accompish (and the shortened version). It's a restaurant simulator.
int main() {
Restaurant i;
string tableID;
cin >> tableID;
i.append(new Table(tableID));//this appends a new table to the linked list
}
//.h file we're not allowed to modify
class Table
{
public:
Table(const string& tableID);//constructor
private:
string* tableID;
}
// .cpp file I'm writing
Table::Table(const string& tableID){
this->tableID = tableID;
}
I'm getting the error:
table.cc:9:18: error: cannot convert ‘const string {aka const std::__cxx11::basic_string}’ to ‘std::__cxx11::string* {aka std::__cxx11::basic_string*}’ in assignment
this->tableID = tableID;
Can anyone tell me what's going on? To me it seems like it's passing the address of tableID in main() and assigning it to a pointer in the constructor, which I thought was legal but maybe it's the const throwing me off.
Several options:
Change the definition of tableID in class Table to be string tableID. In this case you'll keep a copy of the value in the instance.
Change the assignment to this->tableID to be this->tableID = &tableID. In this case you'll assign the address of the tableID parameter to this->tableID. In this case you'll only keep a pointer to the table name in the instance, which could cause some interesting behavior. You'll probably learn the most with this approach.
Change the assignment to this->tableId = new string(tableID). Here you're allocating a new string, populating it with the value of the parameter tableID, and then assigning the address of the new string to the instance var tableID. But because you don't have a destructor defined for this class you'll leak this allocated string every time you destroy an instance to Table.
Perhaps some combination of the above would be best.
Best of luck.

C++11 Initializing a std::string member

When I initialize the std::string member of a class calling its C string constructor, I receive the following errors:
error: expected identifier before string constant
error: expected ',' or '...' before string constant
Although, the program compiles successfully when I use copy initialization or list initialization.
class Element
{
private:
std::string sName_("RandomName"); // Compile error
std::string sName_ = "RandomName"; // OK
std::string sName_{"RandomName"}; // OK
}
What seems to be the problem?
UPDATE
Now I realize this is a stupid question, because, as #p512 says, the compiler will see it as a erroneous method declaration. But I think this question should remain for other people that will do the same thinking error.
std::string sName_("RandomName");
This is an erroneous function declaration - at least that's what the compiler makes of it. Instead you can use something like this:
std::string sName_ = std::string("RandomName");
You can also use initializer lists in the constructor of your class:
class A {
public:
A() : sName_("RandomName") {}
std::string sName_;
};
You can find more on that here: http://en.cppreference.com/w/cpp/language/initializer_list

GCC: Customizing printf for string output

GCC allows customization of printf specifiers. However, I don't see how I can "teach" it to accept my string class for %s specifier. My string class is a simple wrapper over char pointer and has exactly one member variable (char * data) and no virtual functions. So, it's kind of ok to pass it as-is to printf-like functions in place of regular char *. The problem is that on gcc static analyzer prevents me from doing so and I have to explicitly cast it to const char * to avoid warnings or errors.
My cstring looks something like this:
class cstring
{
cstring() : data(NULL){}
cstring(const char * str) : data(strdup(str)){}
cstring(const cstring & str) : data(strdup(str.data)){}
~cstring()
{
free(data);
}
...
const char * c_str() const
{
return data;
}
private:
char * data;
};
Example code that uses cstring:
cstring str("my string");
printf("str: '%s'", str);
On GCC I get this error:
error: cannot pass objects of non-trivially-copyable type 'class cstring' through '...'
error: format '%s' expects argument of type 'char*', but argument 1 has type 'cstring' [-Werror=format]
cc1plus.exe: all warnings being treated as errors
The C++ standard doesn't require compilers to support this sort of code, and not all versions of gcc support it. (https://gcc.gnu.org/onlinedocs/gcc/Conditionally-supported-behavior.html suggests that gcc-6.0 does, at least - an open question whether it will work with classes such as the one here.)
The relevant section in the C++11 standard is 5.2.2 section 7:
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg ...
Passing a potentially-evaluated argument of class type (Clause 9)
having a non-trivial copy constructor, a non-trivial move constructor,
or a non-trivial destructor, with no corresponding parameter, is
conditionally-supported with implementation-defined semantics.
(But look on the bright side: if you get into the habit of using c_str, then at least you won't get tripped up when/if you use std::string.)

Resources