C++ struct declared in function visible in main - c++

why does this code work? with c++14
// Example program
#include <iostream>
#include <string>
using namespace std;
auto fun()
{
struct a
{
int num = 10;
a()
{
cout << "a made\n";
}
~a()
{
cout << "a destroyed\n";
}
};
static a a_obj;
return a_obj;
}
int main()
{
auto x = fun();
cout << x.num << endl;
}
how is the type a visible in main? if i change auto x= to a x= it obviously doesn't compile, but how does main know about the type a?
The static declaration is there since I was trying to test for something else but then I stumbled upon this behavior.
Running it here: https://wandbox.org/permlink/rEZipLVpcZt7zm4j

This is all surprising until you realize this: name visibility doesn't hide the type. It just hides the name of the type. Once you understand this it all makes sense.
I can show you this without auto, with just plain old templates:
auto fun()
{
struct Hidden { int a; };
return Hidden{24};
}
template <class T> auto fun2(T param)
{
cout << param.a << endl; // OK
}
auto test()
{
fun2(fun()); // OK
}
If you look closely you will see this is the same situation as yours:
you have a struct Hidden which is local to fun. Then you use an object of type Hidden inside test: you call fun which returns a Hidden obj and then you pass this object to the fun2 which in turn has no problem at all to use the object Hidden in all it's glory.
as #Barry suggested the same thing happens when you return an instance of a private type from a class. So we have this behavior since C++03. You can try it yourself.

C++14 is made to be more and more tolerant with auto. Your question is not clear, because you're not stating what the problem is.
Now let's tackle your question differently: Why does it not work with a x = ...?
The reason is that the struct definition is not in the scope of the main. Now this would work:
// Example program
#include <iostream>
#include <string>
using namespace std;
struct a
{
int num = 10;
};
auto fun()
{
static a a_obj;
return a_obj;
}
int main()
{
a x = fun();
cout << x.num << endl;
}
Now here it doesn't matter whether you use a or auto, because a is visible for main(). Now auto is a different story. The compiler asks: Do I have enough information to deduce (unambiguously) what the type of x is? And the answer is yes, becasue there's no alternative to a.

Related

C++ does not recognize string as keyword

I tried the following code:
#include <iostream>
using namespace std;
int main()
{
char string[4]='xyz';
return 0;
}
Since string is a keyword the compiler should give error but it runs fine. Can anyone explain why it compiles successfully.
string is not a keyword.
It's the name of a type declared in the standard library.
When you give it a name, you're doing something called shadowing. This is more clear in the following example:
{
int x = 0;
{
int x = 5;
std::cout << x << std::endl;
}
std::cout << x << std::endl;
}
What gets printed?
Well, 5 first then 0.
This is because the x in the second scope overrides the x from the first. It "shadows" the first declaration.
This works with typenames as well:
struct MyStruct {
int x;
};
...
{
...
int MyStruct = 10;
...
}
Here, MyStruct gets overridden within that scope.
That same thing happens in your example with std::string

Template object gets "does not name a type."

I want to create a class that contains a struct with a template. But it gives this error, and though I've seen other similar questions, I don't understand how or if I can declare this in a way that does not give this error. thanks for your help.
# include <iostream>
using namespace std;
template <class T>
class MyTmpl {
public:
MyTmpl() {}
T body;
};
struct s1_t {
std::string s;
int x;
};
MyTmpl<s1_t> myc();
myc.body.s = "s1";
myc.body.x = 7;
int main(int argc, char** argv) {
//std::cout << myc.body.s << ':' << myc.body.x << std::endl;
}
This gives:
x.cpp:24:1: error: 'myc' does not name a type
myc.body.s = "s1";
^
myc.body.s = "s1";
myc.body.x = 7;
Your immediate error is because you have this code where no code should be (at file level, outside of any function). You need to move it into main (or somewhere else that is is allowed to be, but probably main in this case).
The reason you see the does not name a type is simply because code is unexpected at that point so the compiler thinks you're trying to declare something (like, for example, int x;).
You'll get the same error with the code snippet:
//using nontype = int;
nontype x;
because nontype is not actually a type. If you however uncomment the using (a slightly more modern typedef), the nontype becomes a type and the error disappears.
Your second problem is that MyTmpl<s1_t> myc(); is a function declaration, something that would become evident if you included in your main:
auto x = myc();
The linker would then complain about the lack of a myc function definition. You should change it to:
MyTmpl<s1_t> myc; // without the ().
Your third problem is that, while you're using the C++ language, you're not quite yet using the C++ mindset. The whole point of classes is to encapsulate behaviour and state, something that's rather nullified if everything in your class is public :-)
Eventually (with experience), you'll get into the habit of privatising as much as possible, providing constructors, getters, setters, and so forth. Not an immediate issue for you but certainly something you'll want to work toward.
With those changes (other the the "C++ification") and uncommenting your output statement, the following resulting code compiles and runs fine, producing s1:7 as expected:
#include <iostream>
template <class T> class MyTmpl {
public:
MyTmpl() { }
T body;
};
struct s1_t {
std::string s;
int x;
};
MyTmpl<s1_t> myc; // variable, rather than function.
// code not allowed here.
int main() {
myc.body.s = "s1"; // code allowed here.
myc.body.x = 7;
std::cout << myc.body.s << ':' << myc.body.x << std::endl;
}

Declare an object inside a C++ class [duplicate]

I'm beginning to learn C++. In the IDE codeblocks, this compiles:
#include <iostream>
using namespace std;
struct A {};
struct B {
A a;
}
void hi() {
cout << "hi" << endl;
}
int main() {
hi();
return 0;
}
But this doesn't:
struct B {
A a;
}
struct A {};
int main() {
hi();
return 0;
}
void hi() {
cout << "hi" << endl;
}
It gives me the errors:
error: 'A' does not name a type
error: 'hi' was not declared in this scope
Should class/function order matter in C++? I thought it doesn't. Please clarify the issue.
Yes, you must at least declare the class/function before you use/call it, even if the actual definition does not come until afterwards.
That is why you often declare the classes/functions in header files, then #include them at the top of your cpp file. Then you can use the classes/functions in any order, since they have already been effectively declared.
Note in your case you could have done this. (working example)
void hi(); // This function is now declared
struct A; // This type is now declared
struct B {
A* a; // we can now have a pointer to it
};
int main() {
hi();
return 0;
}
void hi() { // Even though the definition is afterwards
cout << "hi" << endl;
}
struct A {}; // now A has a definition

C++ Initialization of static function pointer array

I want to create a static function pointer array, so I can jump to a certain function regarding a received index. Like an index jumper.
So imagine a class like this:
Class A
{
private:
static void 1stFunction();
static void 2ndFunction();
static void(*functionPointer[20])(void);
};
Then I would like that functionPointer to get the value of the 1stFunction and 2ndFunction, and maybe even more.
So, how do I initialize it?
As far as I know, when a static member is declared, you can use it even before an instance is created. So I though, lets initialize that function pointer, so later I can call it like this
functionPointer[receivedIndex]();
So i tried to initilize it like this, in the same .h file
void (*A::functionPointer[])(void) =
{
A::1stFunction,
A::2ndFunction,
};
But the compiler gives me redifinition, it says it's already created.
So, pretty sure I'm missing something. I don't know though, if it is syntax or simply it is not possible to do it this way.
I know that function pointers to class's member functions are different than normal function pointers... But this is a static function, so I believe it doesn't belong to an instance and therefore it should work with normal function pointers.
Any help would be appreciated.
Thanks
The following would be a working example that probably achieves what you need.
You need C++11 for the initializer list.
It is a good practice to initialize the static member in the cpp file, as you don't want to have a definition of the static member everytime the header is included (this can lead to linking issues).
You can call callf with the desired index and have the corresponding function called, based on the initialization of the function pointer array.
The output of the program would be:
I am 2ndFunction
Header file
class A
{
private:
static void Function1();
static void Function2();
static void(*functionPointer[20])();
public:
static void callf(int index);
};
Implementation
#include <iostream>
#include "ex.h"
void(*A::functionPointer[20])() {
A::Function1,
A::Function2
};
void A::Function1() {
std::cout << "I am 1stFunction" << std::endl;
}
void A::Function2() {
std::cout << "I am 2ndFunction" << std::endl;
}
void A::callf(int index) {
A::functionPointer[index]();
}
int main(int argc, char const *argv[]) {
A::callf(1);
return 0;
}
Here you have a more modern C++ approach (C++14 needed)
I would advise you to explore lambda functions if you are not restricted to C++03.
#include <iostream>
#include <functional>
#include <vector>
class A {
public:
using f_type = std::function<void(void)>;
f_type f1 = []() { std::cout << "f0" << std::endl;};
f_type f2 = []() { std::cout << "f1" << std::endl;};
static void f3() { std::cout << "f3" << std::endl; }
std::vector<f_type> functions{f1, f2, f3};
};
int main() {
A a;
a.functions[0]();
a.functions[1]();
//adding custom lambda
a.functions.emplace_back([](){ std::cout << "custom f" << std::endl;});
a.functions[2]();
return 0;
}
you can add both functions and lambdas to your container.

What's the point of initialising an unnamed C++ parameter?

What's the point of initialising an unnamed C++ parameter? For example:
void foo(int = 0) {}
A declaration has no need of a parameter name. The definition does, however. Also, the default parameter cannot be repeated in the definition. Here's a small program that works (but I don't know why you would want to do something like this, really...):
#include <iostream>
void foo(int = 5);
int main() {
foo();
foo(3);
return 0;
}
void foo(int i) {
std::cout << i << std::endl;
}
The output is
5
3
I can imagine in the context of callback functions the construct might be useful:
#include <iostream>
// Please assume the callback is an external library:
typedef void (*callback_function)(int);
callback_function callback;
void foo(int = 0) {
std::cout << "Hello\n";
}
int main() {
callback = foo;
callback(1);
foo();
}
It will serve as the default parameter value. It belongs in the function declaration.