#include <iostream>
class A
{
public:
int func();
protected:
namespace B { enum { D = 0, E = 1 }; }
namespace C { enum { D = 0, E = 1 }; }
}
int A::func()
{
int x = A::B::D;
int y = A::C::E;
return x + y;
}
int main() {
A a;
int x = a.func();
std::cout << x << std::endl; // 1
return 0;
}
What's wrong with this code?
I am just curious and experimenting with namespace, because I'd like to have enums with same names of values.
I don't want to use enum class, because I cannot do operations with integer without overloading operators or casting.
You can't declare a namespace inside a class. Instead, what you can use is a struct like
#include <iostream>
class A
{
public:
int func();
protected:
struct B { enum { D = 0, E = 1 }; };
struct C { enum { D = 0, E = 1 }; };
};
int A::func()
{
int x = A::B::D;
int y = A::C::E;
return x + y;
}
int main() {
A a;
int x = a.func();
std::cout << x << std::endl; // 1
return 0;
}
which you can see working in this live example.
From the C++ 14 Standard (7.3.1 Namespace definition)
2 Every namespace-definition shall appear in the global scope or in a
namespace scope
So these namespace definitions within the class scope (where you forgot to place a semicolon)
class A
{
public:
int func();
protected:
namespace B { enum { D = 0, E = 1 }; }
namespace C { enum { D = 0, E = 1 }; }
};
^^^
are invalid.
Related
I have a bunch of derived structs. Is there any way for me to access the derived width without casting?
If I do this, I get 1s and not 42 and 13:
#include <iostream>
#include <deque>
using namespace std;
struct BaseParams {
virtual ~BaseParams() {}
int width = 1;
};
struct VectorParams : BaseParams {
int width = 42;
};
struct MatrixParams : BaseParams {
int width = 13;
};
int main()
{
std::deque<BaseParams *> params;
VectorParams *vectorParams = new VectorParams;
MatrixParams *matrixParams = new MatrixParams;
params.push_back(vectorParams);
params.push_back(matrixParams);
for (auto ¶m : params) {
std::cout << param->width << std::endl;
}
// Don't want to do this
// for (auto ¶m : params) {
// MatrixParams *matrixParams = dynamic_cast<MatrixParams *>(param);
// if (matrixParams)
// std::cout << matrixParams->width << std::endl;
// VectorParams *vectorParams = dynamic_cast<VectorParams *>(param);
// if (vectorParams)
// std::cout << vectorParams->width << std::endl;
// }
return 0;
}
If possible, I want to avoid casting because I have so many derived structs.
To overwrite the width in BaseParams, instead of making a new variable, you can give VectorParams a constructor like this:
struct VectorParams : BaseParams {
VectorParams() {
width = 42;
}
};
In fact constructors are always how variables are set in new objects. When you write
struct BaseParams {
virtual ~BaseParams() {}
int width = 1;
};
the compiler actually turns it into a constructor, similar to
struct BaseParams {
virtual ~BaseParams() {}
int width;
BaseParams() {
width = 1;
}
};
So I have a header file:
struct inner1 {
int w;
int x;
};
struct inner2 {
int y;
int z;
};
struct outer{
inner1 *a;
inner2 *b;
};
Now in main, I want to initialize these structures and use them. How do I initialize all three structures so that outer recognizes inner1 and inner2 as the specific structs it points to. Then lets say I want to access the variable w. Is it outer.a->w? I am unfamiliar with nested structures dealing with pointers. Any help is appreciated.
struct inner1 {
int w;
int x;
};
struct inner2 {
int y;
int z;
};
struct outer{
inner1 *a;
inner2 *b;
};
int _tmain(int argc, _TCHAR* argv[])
{
outer o;
o.a = new inner1();
o.b = new inner2();
o.a->w = 1;
o.a->x = 2;
o.b->y = 3;
o.b->z = 4;
//do stuff
delete o.a;
delete o.b;
return 0;
}
This will permit you to declare and initialize the structures.
Here is a demonstrative program
#include <iostream>
int main()
{
struct inner1 {
int w;
int x;
};
struct inner2 {
int y;
int z;
};
struct outer{
inner1 *a;
inner2 *b;
};
outer o = { new inner1 { 10, 20 }, new inner2 { 30, 40 } };
std::cout << "o.a->w = " << o.a->w << ", o.a->x = " << o.a->x
<< ", o.b->y = " << o.b->y << ", o.b->z = " << o.b->z
<< std::endl;
delete o.a;
delete o.b;
}
The program output is
o.a->w = 10, o.a->x = 20, o.b->y = 30, o.b->z = 40
Or you could do the following way
#include <iostream>
int main()
{
struct inner1 {
int w;
int x;
};
struct inner2 {
int y;
int z;
};
struct outer{
inner1 *a;
inner2 *b;
};
inner1 i1 = { 10, 20 };
inner2 i2 = { 30, 40 };
outer o = { &i1, &i2 };
std::cout << "o.a->w = " << o.a->w << ", o.a->x = " << o.a->x
<< ", o.b->y = " << o.b->y << ", o.b->z = " << o.b->z
<< std::endl;
}
The approach depends on the task and using of the objects.
You are correct in both your assumptions.
As long as these three structures are defined in this order no further declarations have to be made.
Welcome to c++.
The biggest favour you will do yourself is to learn about the smart pointers early on.
It's almost always a mistake to write structures in terms of raw pointers.
#include <memory>
#include <iostream>
struct inner1 {
inner1(int a, int b) : w(a), x(b) {}
int w;
int x;
};
struct inner2 {
inner2(int a, int b) : y(a), z(b) {}
int y;
int z;
};
struct outer{
outer(int w, int x, int y, int z)
: a(std::make_unique<inner1>(w,x))
, b(std::make_unique<inner2>(y,z))
{}
std::unique_ptr<inner1> a;
std::unique_ptr<inner2> b;
};
int main()
{
auto p_outer = std::make_unique<outer>(1, 2, 3, 4);
return 0;
// p_outer.a and .b are destroyed automatically here
// and all memory is reclaimed.
}
Here I have a very simple program. My aim is to let b equal c, that is to copy all the content of c into b. But I don't know how. The getdata() function returns a pointer pointing to array of objects c, but how can it be used to put c into b?
#include<iostream>
#include<stdlib.h>
using namespace std;
class A
{
public:
A(int i,int j):length(i),high(j){}
int length,high;
};
class B
{
private:
A c[3] = {A(9,9),A(9,9),A(9,9)};
public:
A* getdata()
{
return c;
}
};
int main()
{
A b[3]={A(0,0),A(0,0),A(0,0)};
B *x = new B();
cout<< x->getdata() <<endl;
cout << b[1].length<<endl;
return 0;
}
In modern C++, make yourself a favor and use a convenient container class to store your arrays, like STL std::vector (instead of using raw C-like arrays).
Among other features, std::vector defines an overload of operator=(), which makes it possible to copy a source vector to a destination vector using a simple b=c; syntax.
#include <vector> // for STL vector
....
std::vector<A> v; // define a vector of A's
// use vector::push_back() method or .emplace_back()
// or brace init syntax to add content in vector...
std::vector<A> w = v; // duplicate v's content in w
That's a possible partial modification of your code, using std::vector (live here on codepad):
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A(int l, int h) : length(l), high(h) {}
int length, high;
};
class B
{
private:
vector<A> c;
public:
const vector<A>& getData() const
{
return c;
}
void setData(const vector<A>& sourceData)
{
c = sourceData;
}
};
int main()
{
vector<A> data;
for (int i = 0; i < 3; ++i) // fill with some test data...
data.push_back(A(i,i));
B b;
b.setData(data);
const vector<A>& x = b.getData();
for (size_t i = 0; i < x.size(); ++i) // feel free to use range-for with C++11 compilers
cout << "A(" << x[i].length << ", " << x[i].high << ")\n";
}
Instead of creating an array of A i.e. 'b' in main, create a pointer to A. And then initialize it by calling the getdata().
A *b;
B *x = new B();
b = x->getdata();
Here is an example
#include <iostream>
#include <algorithm>
class A
{
public:
A( int i, int j ) : length( i ), high( j ){}
int length, high;
};
class B
{
private:
A c[3] = {A(9,9),A(9,9),A(9,9)};
public:
A* getdata()
{
return c;
}
};
int main()
{
A b[3] = { A(0,0), A(0,0), A(0,0) };
B *x = new B();
A *c = x->getdata();
std::copy( c, c + 3, b );
for ( const A &a : b ) std::cout << a.length << '\t' << a.high << std::endl;
delete []x;
return 0;
}
The output is
9 9
9 9
9 9
Instead of standard algorithm std::copy you may use an ordinary loop. For example
for ( size_t i = 0; i < 3; i++ ) b[i] = c[i];
The code
#include <iostream>
using namespace std;
template<int n> struct Fibo { static int x; };
template<> int Fibo<0>::x = 1;
template<> int Fibo<1>::x = 1;
template<int n> int Fibo<n>::x = Fibo<n-1>::x + Fibo<n-2>::x; //marked line
int main() {
cout << Fibo<5>::x << endl;
cout << Fibo<4>::x << endl;
cout << Fibo<3>::x << endl;
cout << Fibo<2>::x << endl;
cout << Fibo<1>::x << endl;
cout << Fibo<0>::x << endl;
return 0;
}
outputs
0
0
1
2
1
1
in VC++. (According to user M M. it compiles as expected in gcc). When the compiler gets to the marked line with n=5 it doesn't compile that same line again for n=4, but just treats Fibo<4>::x as if it were declared with
template<> int Fibo<4>::x; // x defaults to 0
Why is that? Why does it work as expected when using
template<int n> struct Fibo { enum { x = Fibo<n-1>::x + Fibo<n-2>::x }; };
template<> struct Fibo<0> { enum { x = 1 }; };
template<> struct Fibo<1> { enum { x = 1 }; };
instead, but not with a static variable? And how do you fix the first code (without enum)?
The Standard is very clear on this:
14.7.1 Implicit instantiation [temp.inst]
9 The implicit instantiation of a class template does not cause any
static data members of that class to be implicitly instantiated.
All the calls in main() to your Fibo<n>::x for n > 1, are explicit instantiations, that through the Fibonnaci recursion will implicitly instantiate Fibo<n-1> and Fibo<n-2> but not their members x. This means that at those points, the static members x will be evaluated to their default initialization of 0. For n=1 and n=0, the compiler will see the explicit initialization values of 1. So effectively, you get the following computation
Fibo<5>::x --> Fibo<4>::x + Fibo<3>::x --> 0 + 0 = 0
Fibo<4>::x --> Fibo<3>::x + Fibo<2>::x --> 0 + 0 = 0
Fibo<3>::x --> Fibo<2>::x + Fibo<1>::x --> 0 + 1 = 1
Fibo<2>::x --> Fibo<1>::x + Fibo<0>::x --> 1 + 1 = 2
Fibo<1>::x --> 1
Fibo<0>::x --> 1
You need to instantiate the static member x before evaluating the Fibonacci recursion. You can do this through a static const int or enum member x, or through a function (possibly constexpr in C++11) as shown by #Jarod42.
I'm not sure if the initialization order of the static variables of template<int n> int Fibo<n>::x = Fibo<n-1>::x + Fibo<n-2>::x; is specified...
You may write this:
template <int N> struct Fibo { int operator()() const { static int x = Fibo<N - 1>()() + Fibo<N - 2>()(); return x; } };
template <> struct Fibo<1> { int operator()() const { static int x = 1; return x; } };
template <> struct Fibo<0> { int operator()() const { static int x = 1; return x; } };
The dependencies are respected.
[Edit]
In a case where the value may be modified (according to your comment), you may use similar technique but returning reference:
template <int N> struct Fibo {
private:
int& operator()() { static int x = Fibo<N - 1>()() + Fibo<N - 2>()(); return x; }
public:
int operator()() const { return const_cast<Fibo&>(*this)(); }
// This change Fibo<0> and Fibo<1> and then update value up to Fibo<N>.
int operator(int fibo0, int fibo1) {
int n_1 = Fibo<N - 1>()(fibo1, fibo2);
(*this)() = n_1 + Fibo<N - 2>()();
}
};
template <> struct Fibo<1> {
private:
int& operator()() { static int x = 1; return x; }
public:
int operator()() const { return const_cast<Fibo&>(*this)(); }
void operator(int fibo0, int fibo1) { Fibo<0>()(fibo0); (*this)() = fibo1; }
};
template <> struct Fibo<0> {
private:
int& operator()() { static int x = 1; return x; }
public:
int operator()() const { return const_cast<Fibo&>(*this)(); }
void operator(int fibo0) { (*this)() = fibo0; }
};
The solution presented by #Jarod42 appears overly complicated to me.
Consider instead the simpler code below.
template<int N>
struct fib {
static const int val = fib<N-1>::val + fib<N-2>::val;
};
template<>
struct fib<0> { static const int val = 0;};
template<>
struct fib<1> { static const int val = 1;};
int main() {
std::cout << fib<45>::val << "\n";
return 0;
}
class Foo {
public:
Foo() { do_something = &Foo::func_x; }
int (Foo::*do_something)(int); // function pointer to class member function
void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }
private:
int func_x(int m) { return m *= 5; }
int func_y(int n) { return n *= 6; }
};
int
main()
{
Foo f;
f.setFunc(false);
return (f.*do_something)(5); // <- Not ok. Compile error.
}
How can I get this to work?
class A{
public:
typedef int (A::*method)();
method p;
A(){
p = &A::foo;
(this->*p)(); // <- trick 1, inner call
}
int foo(){
printf("foo\n");
return 0;
}
};
void main()
{
A a;
(a.*a.p)(); // <- trick 2, outer call
}
The line you want is
return (f.*f.do_something)(5);
(That compiles -- I've tried it)
"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.
class A {
int var;
int var2;
public:
void setVar(int v);
int getVar();
void setVar2(int v);
int getVar2();
typedef int (A::*_fVar)();
_fVar fvar;
void setFvar(_fVar afvar) { fvar = afvar; }
void insideCall() { (this->*fvar)(); }
};
void A::setVar(int v)
{
var = v;
}
int A::getVar()
{
std::cout << "A::getVar() is called. var = " << var << std::endl;
return var;
}
void A::setVar2(int v2)
{
var2 = v2;
}
int A::getVar2()
{
std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
return var2;
}
int main()
{
A a;
a.setVar(3);
a.setVar2(5);
// a.fvar = &A::getVar;
a.setFvar(&A::getVar);
(a.*a.fvar)();
a.setFvar(&A::getVar2);
(a.*a.fvar)();
a.setFvar(&A::getVar);
a.insideCall();
a.setFvar(&A::getVar2);
a.insideCall();
return 0;
}
I extended Nick Dandoulakis's answer. Thank you.
I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.
Try (f.*do_something)(5);
#include<iostream>
using namespace std;
class A {
public:
void hello()
{
cout << "hello" << endl;
};
int x = 0;
};
void main(void)
{
//pointer
A * a = new A;
void(A::*pfun)() = &A::hello;
int A::*v1 = &A::x;
(a->*pfun)();
a->*v1 = 100;
cout << a->*v1 << endl << endl;
//-----------------------------
A b;
void(A::*fun)() = &A::hello;
int A::*v2 = &A::x;
(b.*fun)();
b.*v2 = 200;
cout << b.*v2 << endl;
}
I think calling a non static member of the class could also be done using a static member function.