Use a struct in a function outside of main - c++

To use a struct in a function outside of main(), can you use forward declaration and define it in main(), or does it have to be defined outside of a block?

If you define a structure inside of main(), it will hide the global name of the structure. So the function outside of main() will only be able to reference the global name. This example is taken from the C++ 2011 draft, Section 9.1 p2:
struct s { int a; };
void g() {
struct s; // hide global struct s
// with a block-scope declaration
s* p; // refer to local struct s
struct s { char* p; }; // define local struct s
struct s; // redeclaration, has no effect
}
There is no syntax to refer to the locally defined type from outside the function scope. Because of that, even using a template will fail, because there is no way to express the instantiation of the template:
template <typename F> void bar (F *f) { f->a = 0; }
int main () {
struct Foo { int a; } f = { 3 };
bar(&f); // fail in C++98/C++03 but ok in C++11
}
Actually, this is now allowed in C++11, as explained in this answer.

Related

Does ::myFunction() belongs to global namespace?

I know in C++, we use :: to qualify the namespace for a variable or function, like myNamespace::a. But I notice some usages like ::myFunction(). Does it mean the function belongs to the global namespace?
If the code compiles, then yes, ::myFunction() is referencing the global declaration of myFunction.
This is most commonly used when a local definition shadows your global definition:
namespace local {
int myFunction() {}; // local namespace definition
};
int myFunction() {}; // global definition.
using namespace local;
int main() {
// myFunction(); // ambiguous two definitions of myFunction in current scope.
local::myFunction(); // uses local::myFunction();
::myFunction(); // uses global myfunction();
Yes, it means the variable, type or function following it must be available in the global namespace.
It can be used for example when something is shadowed by a local definition:
struct S {
int i;
};
void f() {
struct S {
double d;
};
S a;
::S b;
static_assert(sizeof(a) != sizeof(b), "should be different types");
}

How to extract the type of an unnamed struct to create a new type within the struct itself?

It's easy to create a method/function parametrized on the type of an unnamed struct. It is also easy to get the type after the struct's definition.
struct Foo {
template <typename T> Foo(T*) { /* we have access to T here */ }
}
template <typename T> void baz(T*) { /* we have access to T here */ }
template<typename T> struct Bar {
/* we have access to T here */
};
void test() {
struct {
Foo foo { this }; // access in a constructor
void test() { baz(this); } // access in a function
} unnamed;
Bar<decltype(unnamed)> bar; // access after definition
}
But is there any "magic" that could allow the use of unnamed's type at the struct scope, or in a static method - not merely within its constructor/instance method or after an instance is declared? It's trivial when the struct is named:
// How to make it work with S absent (an unnamed struct) ?
struct S {
Bar<S> foo; // how to get our type in an unnamed struct?
static void wrapper(void * instance) {
static_cast<S*>(instance)->method(); // how to get our type in an unnamed struct?
}
void method() { ... }
} would_be_unnamed;
This question was motivated by a question about how to implement a destructor in an unnamed struct. The trivial solution there was to wrap a named struct in an unnamed one - such wrapper can then be used in macros without clashing with any other types, etc.
struct { struct S { ... } s; } unnamed;
Solving the type access conundrum would allow a different solution to the motivating question.
Something like this, maybe?
The idea is that you actually have two unnamed structs. Firstly, unnamed contains all the actual code/data and stuff. Then there is unnamedWrapper that, being able to use decltype over unnamed, is just a completely-forwarding (even for constructors!) wrapper around unnamed, with the single speciality that it exports unnamed's type through a typedef.
#include <cstddef>
template<typename T>
size_t templatedSizeof() {
return sizeof(T);
}
struct {
char something;
short somethingElse;
int moreGargabe;
long evenMoreUselessGarbage;
} unnamed;
struct : public decltype(unnamed) {
typedef decltype(unnamed) TheType;
using TheType::TheType; // Use same constructors
} unnamedWrapper;

How to make a function only seen by one function in c++?

How could I make a function only seen by the function that calls it?
define the function I want to hide as private function is not enough, as it could still be seen by other public functions in the class.
Now I use lambda expression to define anonymous function inside function. Is there any better solution?
Aside from using a lambda (which you've rejected), you could implement your function in its own compilation unit, and code the supporting function in an anonymous namespace within that compilation unit.
But that supporting function would be outside the class, so you'd have to pass it all the parameters it needed. That could become unwieldly though no worse than a long lambda capture list.
You can use a function object. For example(you can compile this, even in C++03):
#include <iostream> // only for output
class foo{
int bar(){return 0;} // Only foo can see this
public:
int operator()(){
return bar();
}
};
class baz{
public:
foo do_foo;
};
int main(){
baz a;
std::cout << a.do_foo() << std::endl;
}
the method bar is only visible by a foo.
P.S.: If you need foo to access members of baz, make it a friend.
A simmilar approach to cassiorenan would be to use static class functions and friends.
Something like this:
void Boss();
class Worker {
static void Test(){ return;}
friend void Boss();
};
void Boss(){
Worker::Test();
}
Though why would you want to do this, I don't know.
It is possible to define function inside a function without lambdas. Just define a struct that contains required function. This approach is not much better than using lambda, but at least this is straightforward and works with older compilers too.
int func() {
struct {
int hiddenFunc() {
return 1;
}
} h;
int a = h.hiddenFunc() + h.hiddenFunc();
return a;
}
As a slight variation from cassiorenan's solution, you could use a class containing one public static function (the visible function) and one static private function that could only be called from there. To avoid creation of objects of that class, it is enough to put a private constructor.
EDIT:
Per cassiorenan's comment, I can see that OP really needs methods and not functions. In that case, I would still use a dedicated class in a anonymous namespace to ensure it is not visible from elsewhere (even if my example is single file ...) friend to the class really used. So in below example, bar is the business class that would have a method with an externally hidden implementation (here relay_method), and foo is dedicated to the hidden method called with a pointer to the real object. In real world, the whole anonymous namespace and the implementation of the hidden method should be in the implementation file bar.cpp.
That way, the real implementation function priv_func can only be called from a bar object through bar::relay_method() and foo::bar_func(bar &).
#include <iostream>
class bar;
namespace {
class foo {
private:
static int priv_func(int i) {
return i * i;
}
foo() {}
public:
// only useful if true functions were needed
/* static int pub_func(int i, int j) {
return priv_func(i) + priv_func(j);
}*/
static void bar_func(bar& b);
};
}
class bar {
int x;
int x2;
public:
bar(int i): x(i) {}
void relay_method() {
foo::bar_func(*this);
}
friend class foo;
int getX2() const {
return x2;
}
};
void foo::bar_func(bar& b) {
b.x2 = foo::priv_func(b.x);
}
using namespace std;
int main() {
/* int i = foo::pub_func(3,4);
cout << i << endl;
// foo::priv_func(2); error access to private member of class foo
// foo f; */
bar b(2);
b.relay_method();
cout << b.getX2() << endl;
return 0;
}

access private member using template trick

From a blog post Access to private members: Safer nastiness by Johannes Schaub - litb:
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// use
struct A {
A(int a):a(a) { }
private:
int a;
};
// tag used to access A::a
struct A_f {
typedef int A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::a>;
int main() {
A a(42);
std::cout << "proof: " << a.*get(A_f()) << std::endl;
}
how get function can be call from a object since its not defined inside class A ?
EDIT:
I don't understand why get must have Tag as parameter instead of a.*get<A_f>()
=> ok it's due to ADL mechanism
You are not calling get from a! Actually what get return is a class pointer to a member inside A and type of it is int A::* so you need an instance of A to access that value.
For example let me play a little with your code:
struct A {
A(int a):a(a) { }
int b;
private:
int a;
};
void test() {
auto p = &A::b;
std::cout << a.*p << std::endl;
}
Did I call p from inside a? a does not have p, this is exactly what happened in your code, get function return &A::a and you use a to read its value! that's all, nothing is wrong and I think it will be compiled in all compilers.
One other question here is: Why C++ allow declaring template using private member of A. C++ standard say:
14.7.2p8 The usual access checking rules do not apply to names used to specify explicit instantiations. [Note: In particular, the template
arguments and names used in the function declarator (including
parameter types, return types and exception specifications) may be
private types or objects which would normally not be accessible and
the template may be a member template or member function which would
not normally be accessible.]
But if you try to instantiate or even typedef specified template then you get an error.
Let's modify your example slightly:
struct A {
private:
int a;
friend void f();
};
// Explicit instantiation - OK, no access checks
template struct Rob<A_f, &A::a>;
// Try to use the type in some way - get an error.
struct Rob<A_f, &A::a> r; // error
typedef struct Rob<A_f, &A::a> R; // error
void g(struct Rob<A_f, &A::a>); // error
// However, it's Ok inside a friend function.
void f() {
Rob<A_f, &A::a> r; // OK
typedef Rob<A_f, &A::a> R; // OK
}
It's legal because friend functions are always in the global scope, even if you implement them inside a class. In other words, this:
class A
{
friend void go() {}
};
is just a shortcut for:
class A
{
friend void go();
};
void go() {}
This is a known compiler bug in gcc and was fixed in a later release.
See-:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41437

Local Classes in C++

I am reading "Local Classes" concept in Object-oriented programming with C++ By Balagurusamy (http://highered.mcgraw-hill.com/sites/0070593620/information_center_view0/).
The last line says "Enclosing function cannot access the private members of a local class. However, we can achieve this by declaring the enclosing function as a friend."
Now I am wondering how the highlighted part can be done?
Here is the code I was trying but no luck,
#include<iostream>
using namespace std;
class abc;
int pqr(abc t)
{
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know the code looks erroneous, any help would be appreciable.
Your friend statement is fine.
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
friend int pqr();
};
return abc().x;
}
int main() {
cout << "Return " << pqr() << endl;
}
Edit:
IBM offers this explanation for the issue raised in the comments:
If you declare a friend in a local class, and the friend's name is unqualified, the compiler will look for the name only within the innermost enclosing nonclass scope. [...] You do not have to do so with classes.
void a();
void f() {
class A {
// error: friend declaration 'void a()' in local class without prior decl...
friend void a();
};
}
friend void a(): This statement does not consider function a() declared in namespace scope. Since function a() has not been declared in the scope of f(), the compiler would not allow this statement.
Source: IBM - Friend scope (C++ only)
So, you're out of luck. Balagurusamy's tip only works for MSVC and similar compilers. You could try handing off execution to a static method inside your local class as a work-around:
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
static int pqr() {
return abc().x;
}
};
return abc::pqr();
}
There seems to be a misunderstand about local classes.
Normally there are here to help you within the function... and should NOT escape the function's scope.
Therefore, it is not possible for a function to take as an argument its own local class, the class simply isn't visible from the outside.
Also note that a variety of compilers do not (unfortunately) support these local classes as template parameters (gcc 3.4 for example), which actually prevents their use as predicates in STL algorithms.
Example of use:
int pqr()
{
class foo
{
friend int pqr();
int x;
foo(): x() {}
};
return foo().x;
}
I must admit though that I don't use this much, given the restricted scope I usually use struct instead of class, which means that I don't have to worry about friending ;)
I have no solution for the friend thing yet (don't even know if it can be done), but read this and this to find out some more about local classes. This will tell you that you cannot use local classes outside the function they are defined in (as #In silico points out in his answer.)
EDIT It doesn't seem possible, as this article explains:
The name of a function first introduced in a friend declaration is in the scope of the first nonclass scope that contains the enclosing class.
In other words, local classes can only befriend a function if it was declared within their enclosing function.
The friend int pqr(abc); declaration is fine. It doesn't work because the abc type has not been defined before you used it as a parameter type in the pqr() function. Define it before the function:
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// Class defined outside the pqr() function.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
// At this point, the compiler knows what abc is.
int pqr(abc t)
{
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know you want to use a local class, but what you have set up will not work. Local classes is visible only inside the function it is defined in. If you want to use an instance of abc outside the pqr() function, you have to define the abc class outside the function.
However, if you know that the abc class will be used only within the pqr() function, then a local class can be used. But you do need to fix the friend declaration a little bit in this case.
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// pqr() function defined at global scope
int pqr()
{
// This class visible only within the pqr() function,
// because it is a local class.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
// Refer to the pqr() function defined at global scope
friend int ::pqr(); // <-- Note :: operator
} t;
t.xyz();
return t.x;
}
int main()
{
cout<<"Return "<<pqr()<<endl;
}
This compiles without warnings on Visual C++ (version 15.00.30729.01 of the compiler).