C++11 Initializing a std::string member - c++11

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

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{}};

initialize a string size during declaration

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, ' ');

No member named value in std::is_convertible when using clang

In a very simple situation with a constrained constructor, testing for convertibility of the argument, an error is produced in clang, but not in g++:
#include <type_traits>
template <class T, class U>
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
template <class T>
struct A
{
template <class S, class = std::enable_if_t<Convertible<S,T>> >
A(S const&) {}
};
int main()
{
A<double> s = 1.0;
}
Maybe this issue is related to Is clang's c++11 support reliable?
The error clang gives, reads:
error: no member named 'value' in 'std::is_convertible<double, A<double> >'
constexpr bool Convertible = std::is_convertible<T,U>::value && std::is_convertible<U,T>::value;
~~~~~~~~~~~~~~~~~~~~~~~~~~^
I've tried
g++-5.4, g++-6.2 (no error)
clang++-3.5, clang++-3.8, clang++-3.9 (error)
with argument -std=c++1y and for clang either with -stdlib=libstdc++ or -stdlib=libc++.
Which compiler is correct? Is it a bug in clang or gcc? Or is the behavior for some reasons undefined and thus both compilers correct?
First of all, note that it works fine if you use:
A<double> s{1.0};
Instead, the error comes from the fact that you are doing this:
A<double> s = 1.0;
Consider the line below (extracted from the definition of Convertible):
std::is_convertible<U,T>::value
In your case, this is seen as it follows (once substitution has been performed):
std::is_convertible<double, A<double>>::value
The compiler says this clearly in the error message.
This is because a temporary A<double> is constructed from 1.0, then it is assigned to s.
Note that in your class template you have defined a (more or less) catch-all constructor, so a const A<double> & is accepted as well.
Moreover, remember that a temporary binds to a const reference.
That said, the error happens because in the context of the std::enable_if_t we have that A<double> is an incomplete type and from the standard we have this for std::is_convertible:
From and To shall be complete types [...]
See here for the working draft.
Because of that, I would say that it's an undefined behavior.
As a suggestion, you don't need to use std::enable_if_t in this case.
You don't have a set of functions from which to pick the best one up in your example.
A static_assert is just fine and error messages are nicer:
template <class S>
A(S const&) { static_assert(Convertible<S,T>, "!"); }

C++11 implicit copy constructor while implementing explicitly a constructor

I ran into a problem. I implemented a constructor for a class, but why are implicitly generated the other constructors, like the copy one?
I thought, that if I define a constructor explicitly, then the compiler doesn't generates implicitly other ones. I'm really hoping, that this a VC++ specific thing, and that this code doesn't conforms to ISO:IEC C++11:
class Foo
{
int bar;
public:
Foo(int&& arg) : bar(arg) { cout << "RConstruction" << endl; }
};
int main(int, const char*[])
{
Foo f = Foo(42);
/* Create unused temporary on the stack */
Foo::Foo(f); /* calling Foo::Foo(const Foo&): this shouldn't work... */
return (0);
}
Please keep in mind, that this is a sample code, created exactly for this situation, for demonstration purposes, I expect answers only that strictly relate to this question.
That's not a move constructor, so it doesn't suppress any implicit ones.
Just like Foo(const int&) isn't a copy constructor, Foo(int&&) isn't a move constructor, it's just a constructor taking an rvalue reference.
A move constructor looks like one of:
Foo(Foo&&)
Foo(const Foo&&)
Foo(volatile Foo&&)
Foo(const volatile Foo&&)
I thought, that if I define a constructor explicitly, then the compiler doesn't generates implicitly other ones.
If you define any constructor the compiler doesn't generate the default constructor, but it still generates the others. Define the as deleted if you don't want them:
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
You did not declare a move constructor, but a regular constructor : no implicit constructor will be deleted.
A move constructor would be of the form Foo(Foo&& arg) (with any cv-qualifier on the argument)
Also note that this statement is not valid C++ :
Foo::Foo(f);
Maybe you meant :
Foo g = Foo(f);

Resources