I have been trying to understand this but can't get it to work. My impression is that this should work:-
template <int I> struct banana {
int getNumber() { return 5; }
int getNumber<0>() { return 6; }
};
So if I make a new banana with any template parameter other than 0, getNumber() should return 5 and if the parameter is 1, it should return 6. Why is it not working?
Because that's not the way to specialize. What you need is
#include <iostream>
template <int I> struct banana {
int getNumber() { return 5; }
//int getNumber<0>() { return 6; } // WRONG
};
template<> int banana<0>::getNumber(){ return 6;} // CORRECT WAY OF SPECIALIZING
int main()
{
banana<42> foo;
banana<0> bar;
std::cout << foo.getNumber() << std::endl; // outputs 5
std::cout << bar.getNumber() << std::endl; // outputs 6
}
Live on Coliru
There are 2 ways to get what you want... depending on what you want.
expanding on vsoftco's answer:
#include <iostream>
template <int I>
struct banana {
int getNumber() { return 5; }
};
template<>
struct banana<0>
{
int getNumber() { return 6; }
};
struct banana2
{
template<int I> int getNumber() { return 5; }
};
template<>
int banana2::getNumber<0>() { return 6; }
using namespace std;
auto main() -> int
{
banana<42> foo;
banana<0> bar;
std::cout << foo.getNumber() << std::endl;
std::cout << bar.getNumber() << std::endl;
banana2 b2;
std::cout << b2.getNumber<400>() << std::endl;
std::cout << b2.getNumber<0>() << std::endl;
return 0;
}
expected output:
5
6
5
6
Related
Does this code architecture cause memory leakage by not freeing m_func?
And could this be tempered with if this code would be executed at a closed server? Like finding the address of the pointer and replacing the code of the function pointee with malicious code? If so how could I solve this?
#include <iostream>
template <typename Func>
struct endpoint_t {
void* m_func;
endpoint_t(Func&& func) : m_func((void*) func) {}
auto execute() {
return ((Func*) m_func)();
}
};
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int main() {
endpoint_t end(hello_world);
end.execute();
}
Edit:
This is the actual goal of the code: To store multiple endpoint functions inside a vector.
#include <vector>
#include <iostream>
template <typename Func>
struct endpoint_t {
void* m_func;
endpoint_t(Func&& func) : m_func((void*) func) {}
auto execute() {
return ((Func*) m_func)();
}
};
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int hello_world2() {
std::cout << "Hello World 2! \n";
return 0;
}
int main() {
std::vector<endpoint_t<???>> array;
array.push_back(hello_world);
array.push_back(hello_world2);
}
Assuming the prototypes of all your 'hello world' functions is the same (int return value, no parameter), you don't need templates at all. Just store a function pointer.
typedef int (*Func_t)();
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int hello_world2() {
std::cout << "Hello World 2! \n";
return 0;
}
int main() {
std::vector<Func_t> array;
array.push_back(&hello_world);
array.push_back(&hello_world2);
}
Assuming that the prototypes do differ, it becomes a wee bit more difficult, but not very much so, thanks to std::function.
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int hello_world2(int value) {
std::cout << "Hello World 2! \n";
return 0;
}
int main() {
std::vector<std::function<int ()>> array;
array.push_back(&hello_world);
array.push_back(std::bind(&hello_world2, 2));
}
Please note, that std::bind and lambdas require you to pass any given parameter at the time of binding. You cannot add the parameter later.
How can I pass a structure name, object name, different member name(whose value to be verified) as a parameter to a function ?
struct st{
int a;
int b;
}
bool verify(____ st , ____ b){
if(obj.b == 5)return true;
return false;
}
int main(){
st obj;
// now that I know all the names of members of struct name
// HOW can I verify passing different member name as parameter
cout<<verify(__,__);
}
For an instance:
(example with error)
#include<iostream>
using namespace std;
struct st{
int a;
int b;
};
bool verify(st obj, st.a val){
if(obj.a==val)
return true;
}
int main()
{
cout<<"Hello World"<<endl;
st obj;
cout<<verify(obj,a);
//cout<<verify(obj,b);
return 0;
}
You can use a pointer to data member:
bool verify(const st &obj, int st::* field) {
return obj.*field == 5;
}
...
st obj;
std::cout << verify(obj, &st::a);
std::cout << verify(obj, &st::b);
But the syntax is confusing and just passing a reference to the data member to verify is easier:
bool verify(int field) {
return field == 5;
}
...
st obj;
std::cout << verify(obj.a);
std::cout << verify(obj.b);
Using a template:
#include <iostream>
struct st
{
int a;
int b;
};
struct st2
{
int c;
int d;
};
template<typename T>
bool verify(const T &obj, int T::* field)
{
return obj.*field == 5;
}
int main()
{
st obj = {5, 6};
st2 obj2 = {5, 6};
std::cout << verify(obj, &st::a) << "\n"; // 1, since obj.a is 5
std::cout << verify(obj2, &st2::d) << "\n"; // 0, since obj.d is not 5
return 0;
}
Is it possible to use a lambda function to create an alias to a template class function? Something like this:
#include <iostream>
using namespace std;
int calcDouble(int a) { return a * 2; }
int calcMultiply_10(int a) { return a * 10; }
struct foo
{
template<void (*func)(int)>
int generic(int value)
{
return func(value);
}
static auto double_10 = [this] { generic<calcDouble>(10); };
static auto double_20 = [this] { generic<calcDouble>(20); };
static auto multiply_10_20 = [this] { generic<calcMultiply_10>(20); };
}
int main() {
foo f;
cout << "double_10: " <<f.double_10() << endl;
cout << "double_20: " <<f.double_20() << endl;
return 0;
}
Your particular example doesn't compile, and would be dangerous if it did - capturing this by value means that as soon as the class is copied/moved the captured this will point to a wrong or invalid memory location.
Just use member functions:
auto double_10() { return generic<calcDouble>(10); }
auto double_20() { return generic<calcDouble>(20); }
auto multiply_10_20() { return generic<calcMultiply_10>(20); }
live example on wandbox
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.