Using class alias for its constructor definition [duplicate] - c++

This question already has answers here:
Can typedef names be used to declare or define constructors?
(2 answers)
Closed 7 months ago.
This minimum reproducible piece of code
class MyClass
{
public:
explicit MyClass();
~MyClass();
};
using MyClassAlias = MyClass;
MyClassAlias::MyClassAlias()
{
}
MyClassAlias::~MyClassAlias()
{
}
int main()
{
MyClassAlias obj;
return 0;
}
gives the error:
a.cpp:11:1: error: ISO C++ forbids declaration of ‘MyClassAlias’ with no type [-fpermissive]
11 | MyClassAlias::MyClassAlias()
| ^~~~~~~~~~~~
a.cpp:11:1: error: no declaration matches ‘int MyClass::MyClassAlias()’
a.cpp:11:1: note: no functions named ‘int MyClass::MyClassAlias()’
a.cpp:1:7: note: ‘class MyClass’ defined here
1 | class MyClass
| ^~~~~~~
Only if I replace MyClassAlias::MyClassAlias() with MyClassAlias::MyClass(), it gets cured. At the same time, as you can see, it is okay to have MyClassAlias::~MyClassAlias() (the compiler gives no error).
Is there any way to fix this: to have consistency in naming?

The "names" (although these are not names in the technical sense of the standard) of the constructor and destructor are MyClass and ~MyClass respectively. They are based on the injected class name. You need to use these two to define them or write any declaration for them. You cannot use an alias name for these.
The same does not apply to the class name before the ::. It can be the name of an alias.
It seems that GCC accepts the alias as well for the destructor definition, but as far as I can tell that is not standard-conforming.

Related

Why doesn't this class forward declaration compile in C++? [duplicate]

This question already has answers here:
C++ class declaration after using it
(3 answers)
What are forward declarations in C++?
(8 answers)
Closed 3 months ago.
I'm sure that this has been asked, but I cannot find the question or answer, so here is the minimal code I tried to compile.
// goof4.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
class A;
class B
{
public:
A func() { return A{}; }
};
class A
{
};
int main()
{
B b;
auto a = b.func();
}
The declaration of B::func gives a "use of undefined type 'A' Error C2027 in MSVC 2022 using /std:c++20. I would have thought that the forward declaration of "class A" would have allowed the compiler to work on B::func until such time as class A was defined. Any help?
Because you have the function body using the (at that point) undefined type A in the class B itself and in a function body the type must already be defined.
just do A funct(); in the class B itself
and put the function body and after defining A,
A B::funct() { return A{}; }
https://ide.geeksforgeeks.org/2db37ea7-a62c-487b-8af5-10af8cebc3c6

Why does constexpr attribute not work when applied to a static method? [duplicate]

This question already has answers here:
Why is this constexpr static member function not seen as constexpr when called?
(2 answers)
Closed 5 years ago.
Consider this trivial test code:
class Test
{
public:
Test() {/* empty */}
private:
enum {BLAH = 42};
static constexpr int Magic() {return BLAH*4;}
float f[Magic()];
};
int main(int argc, char ** argv)
{
Test t;
return 0;
}
When I try to compile it (under MacOS/X using clang++ from the latest XCode), I get this compiler error:
Jeremys-Mac-Pro:~ jaf$ clang++ -std=c++11 ./test.cpp
./test.cpp:11:14: error: fields must have a constant size: 'variable length
array in structure' extension will never be supported
float f[Magic()];
Can anyone explain why this is an error? For comparison, if I move the Magic() method out of the Test class and make it a free-standing function, it compiles as expected, but I don't really want to do that because I want to keep Magic() and BLAH private to the Test class if possible.
(Note: I'm not trying to use variable-length arrays here; rather I'm trying to declare an array whose size is determined by the computation of a function at compile-time)
It's because functions within a class aren't processed until the class is complete. This rule allows a function defined within a class to access members of that class that are defined later in the class than that function. As a result, Magic() does not yet have a definition, so can't be evaluated at that moment of compile time.
This is correct behavior, though the error the various compilers generate are not helpful for understanding the problem.
The formal rules are in the C++ standard at [class.member]/6:
A class is considered a completely-defined object type (6.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Possible bug in unique_ptr implementation [duplicate]

This question already has answers here:
Unique_ptr and forward declaration
(2 answers)
Closed 6 years ago.
I was trying to use unique_ptr class member with forward declaration. As numerous sources says e.g. Forward declaration with unique_ptr? it should be sufficient to declare non inline destructor, but it seems not to be a case in VS2013 and GCC 5.3.1. I didn't test other compilers.
Example:
#include <memory>
class B;
class A {
public:
//A();
~A();
private:
std::unique_ptr<B> b;
};
//class B { };
int main() {
A a;
}
I can make this code compile only after uncommenting the ctor declaration or the class B declaration. Otherwise on VS2013 I get error
error C2338: can't delete an incomplete type
on GCC error:
In file included from /usr/local/include/c++/5.3.0/memory:81:0,
from main.cpp:1:
/usr/local/include/c++/5.3.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = B]':
/usr/local/include/c++/5.3.0/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = B; _Dp = std::default_delete<B>]'
main.cpp:5:7: required from here
/usr/local/include/c++/5.3.0/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'B'
static_assert(sizeof(_Tp)>0,
^
Why is this?
The destructor of class A must know the definition of class B. A forward declaration of class B is okay as longs as the implementation file of the constructor/destructor of A knows the definition of class B. If your implementation is (implicitly) in a header file then you need a definition of B in your header file. You may study Pimpl from Herb Sutter.

C++ Why is variable a function and not an object? [duplicate]

This question already has answers here:
C++'s most vexing parse again [duplicate]
(2 answers)
Closed 8 years ago.
This title may not be completely accurate--it's based on my best guess on what is happening and I figured it was better than "Can someone explain what is happening with this code?"
Anyway, I have this code:
class Class1 { };
class Class2
{
public:
Class2(Class1 other){}
};
void func(Class2 x){}
int main()
{
Class2 x(Class1());
func(x); //Compile Error
Class1 y1;
Class2 y2(y1);
func(y2); //Compiles fine
return 0;
}
So when I compile it, the line marked as "Compile Error" provides an error in g++ 4.9:
main.cpp: In function ‘int main()’:
main.cpp:14:10: error: could not convert ‘x’ from ‘Class2 (*)(Class1 (*)())’ to ‘Class2’
func(x);
^
clang++ 3.4.1 provides a similar error.
My best guess is that it thinks that "x" is some sort of function that returns a Class2, instead of a Class2 itself, but...why is this happening? I would think that the call to Class1 returns some anonymous Class1 which is passed into Class2's constructor.
Class2 x(Class1()); is a function declaration due to a vexing parse (google skills come in handy here).
Alternative:
Class2 x((Class1()));
Class2 x{Class1()};
This is because this line
Class2 x( Class1());
declares a function actually and not an object. This is known as vexing parse.
To avoid this issue you should write:
Class2 x((Class1()));
or
Class1 y;
Class2 x( y);

Is initializing non static members allowed outside of a class constructor?

I just saw a question where a non static member of a class was initialized in the class definition. But if I try to compile the following code I get an error from the compiler.
class MyClass
{
int n = 2;
};
The error I'm getting is:
g++ -o ns nonstatic.cpp -Wall -Wextra -pedantic
nonstatic.cpp:3:13: error: ISO C++ forbids initialization of member ‘n’ [-fpermissive]
nonstatic.cpp:3:13: error: making ‘n’ static [-fpermissive]
nonstatic.cpp:3:13: error: ISO C++ forbids in-class initialization of non-const static member ‘n’
I always thought I must initialize such member in the constructor like this:
class MyClass
{
public:
MyClass ( void ) : n(2) {}
private:
int n;
};
Or with n initialized inside of the body of the constructor.
So my question is: when is one allowed to initialize a non static member outside the context of a class constructor?
kind regards,
when is one allowed to initialize a non static member of a class in C++?
One can do this already in C++11.
Just pass in -std=c++11 to the command line and you'll be able to.