usage of using keyword in struct C++ [duplicate] - c++

This question already has answers here:
Constructor nominated by using declaration
(1 answer)
Using-declaration for base class constructors
(1 answer)
Closed 3 months ago.
I created an exception like this in my header_file run.h
struct invalid_assignment : std::runtime_error {
using std::runtime_error::runtime_error;
};
I dont understand the using std::runtime_error::runtime_error; part.
This looks unecessary.

From the C++ 17 Standard (10.3.3 The using declaration)
3 In a using-declaration used as a member-declaration, each
using-declarator’s nested-name-specifier shall name a base class of
the class being defined. If a using-declarator names a constructor,
its nested-name-specifier shall name a direct base class of the class
being defined.
and
16 For the purpose of overload resolution, the functions that are
introduced by a using-declaration into a derived class are treated as
though they were members of the derived class. In particular, the
implicit this parameter shall be treated as if it were a pointer to
the derived class rather than to the base class. This has no effect on
the type of the function, and in all other respects the function
remains a member of the base class. Likewise, constructors that are
introduced by a using-declaration are treated as though they were
constructors of the derived class when looking up the constructors of
the derived class (6.4.3.1) or forming a set of overload candidates
(16.3.1.3, 16.3.1.4, 16.3.1.7). If such a constructor is selected to
perform the initialization of an object of class type, all subobjects
other than the base class from which the constructor originated are
implicitly initialized (15.6.3).
Thus this using declaration
using std::runtime_error::runtime_error;
introduces constructors of the class std::runtime_error in the class invalid_assignment as if they are constructors of the class invalid_assignment.

Related

Using declaration in class refers into 'std::', which is not a class [duplicate]

This question already has answers here:
error: using-declaration for non-member at class scope using std::cout
(3 answers)
usage of using keyword in struct C++ [duplicate]
(1 answer)
Closed 9 days ago.
I'm trying to unlearn using namespace std, considering https://www.youtube.com/watch?v=MZqjl9HEPZ8
So I tried
// using namespace std;
struct Data
{
using std::shared_ptr;
shared_ptr<char[]> m_name = nullptr;
// std::shared_ptr<char[]> m_name = nullptr;
};
And from that I got
main.cpp:14:11: Using declaration in class refers into 'std::', which is not a class
It seems I cannot do using std::shared_ptr; inside class declaration?
Am I missing something or really need to type std::shared_ptr there?
Certain forms of using don't work in class bodies. This includes using namespace and using X where X isn't inherited from the base class.
using std::shared_ptr; works if you move it to the global scope.
using X = Y; does work at class scope. In your case, it would be template <typename T> using shared_ptr = std::shared_ptr<T>;. But note that in rare cases it's slightly different from spelling it as std::shared_ptr (e.g. when passing it to template template parameters).
[do I] really need to type std::shared_ptr there?
You should type std::shared_ptr. Omitting std:: often causes confusion. "Is it something from std:: or something custom?"
From the C++ 17 Standard (10.3.3 The using declaration)
3 In a using-declaration used as a member-declaration, each
using-declarator’s nested-name-specifier shall name a base class of
the class being defined. If a using-declarator names a constructor,
its nested-name-specifier shall name a direct base class of the class
being defined.
std::shared_ptr is not a member of a base class of the class Data in your code example.
So the compiler issues an error.
std:;shared_ptr is a class declared in the namespace std. It is not even a member of some class.

What is using T::T [duplicate]

This question already has an answer here:
Questions about template and typename [duplicate]
(1 answer)
Closed 5 months ago.
I read this article but I don't understand the meaning of this part of the code:
template <typename T> struct counted : T, private instance_counter<T>
{
using T::T;
};
It must be something simple as "make visible all names from namespace" but I don't completely understand it.
T is the base class.
T::T is/are the constructor(s) of the base class T. A constructor has the same name as the class being constructed.
using T::T; brings the constructor(s) of the base class into the current scope, which is the derived class counted.
This line allows counted to be constructed using any constructor that T allows.
make visible all names from namespace
No, because T isn't a namespace. You can't derive from a namespace.
The using keyword has more than one meaning.
You're thinking of the using directive for namespaces, but the using declaration works for both namespace members (at namespace scope) and class members (inside a class). Since we already established T is not a namespace, this is obviously the second case.
Inside a class using T::member would normally just prevent base-class names being hidden by the derived class, but T::T means the base class constructor, which as a special case inherits constructors from T.
template <typename T> struct counted : T
{
using T::T; // now counted<T> can directly use any of T's constructors
};

C++ visibility of inherited constructor [duplicate]

This question already has an answer here:
C++11 inheriting constructors and access modifiers
(1 answer)
Closed 3 years ago.
When I use using like this why is the constructor inherited publicly?
class Base {
int x;
public:
Base(int x);
};
class Derived : public Base {
using Base::Base;
};
I can now do:
Derived d (2);
I thought that using declarations had the visibility of where they are situated. Here, it should be private.
From The C++ Programming Language:
A name brought into a derived
class scope by a using-declaration has its access determined by the placement of the using-declaration;
According to the C++17 Standard (10.3.3 The using declaration)
19 A synonym created by a using-declaration has the usual
accessibility for a member-declaration. A using-declarator that names a
constructor does not create a synonym; instead, the additional
constructors are accessible if they would be accessible when used to
construct an object of the corresponding base class, and the
accessibility of the using-declaration is ignored.

Are C++ type-attributes inherited? [duplicate]

This question already has an answer here:
Does attribute specifier sequence inherit?
(1 answer)
Closed 4 years ago.
I think it's not really a duplicate of Are function attributes inherited?, because I'm wondering about classes, not member functions :
struct [[nodiscard]] error {};
struct critical_error : error {};
critical_error foo();
int main() {
foo(); // no warning.
}
It seems that the [[nodiscard]] attribute is not inherited here. Is it the same for all type-attributes?
They aren't, as you asserted yourself. The standard is explicit in what exactly is inherited from a base class to a derived one:
10.6 Derived classes [class.derived]
2 [...] Unless redeclared in the derived class, members of a base class are also considered to be members of the derived class.
Members of a base class other than constructors are said to be inherited by the derived class.
Constructors of a base class can also be inherited as described in [namespace.udecl].
Inherited members can be referred to in expressions in the same manner as other members of the derived class, unless their names are hidden or ambiguous ([class.member.lookup]).
For the sake of completeness: There is also no wording about inheritance in the specific section about attributes.
Basically: an attribute is not a member of the class or a constructor, so it can't be inherited.

Placing class constructor [duplicate]

This question already has answers here:
Why does decltype not see the member declaration? [duplicate]
(3 answers)
Closed 5 years ago.
Why this code is incorrect?
class Method
{
public:
Method(decltype(info2) info1);
virtual ~Method(){}
protected:
QSharedPointer<info> info2;
};
But this code is correct:
class Method
{
public:
virtual ~Method(){}
protected:
QSharedPointer<info> info2;
public:
Method(decltype(info2) info1);
};
why place of class constructor is important?
I thought that place of definition class constructor isnt important.
I believe this part of the standard is relevant [basic.scope.class]/1.1:
The potential scope of a name declared in a class consists not only of the declarative region following the
name’s point of declaration, but also of all function bodies, default arguments,
exception-specification
s,
and
brace-or-equal-initializers
of non-static data members in that class (including such things in nested
classes).
Note that it only mentions default arguments. So this works since the decltype is referred in a default argument:
Method(QSharedPointer<int> info1 = decltype(info2)())
And this also works since it's inside a body:
Method(<...>)
{
decltype(info2) info3;
}
However your example does not work because such a placement of a decltype is not covered by the paragraph I quoted, thus the name info2 is considered out of scope.
Place of QSharedPointer info2;
is important.
'info2' should be defined before using it into decltype (http://en.cppreference.com/w/cpp/language/decltype).
Next would not work either:
void f() {
d();
}
void d() {
}