How do I declare that I want a const function reference (in a template parameter)? eg,
template< bool (&func)(int arg) >
void foo(int stuff);
but const?
More concretely, if I try to compile the following with icpc
:
template<bool (&func)(int arg)>
bool id(int arg) {
return func(arg);
}
class Foo {
public:
Foo() {};
virtual ~Foo() {};
bool bar(int arg) { return true; }
bool bar2(int arg) {
return id<bar>(arg);
};
};
int main() {
return 0;
}
I get
$ icpc foo.cpp
foo.cpp(12): error: no instance of function template "id" matches the argument list
argument types are: (int)
return id<bar>(arg);
^
compilation aborted for foo.cpp (code 2)
or, with g++
, I get
$ g++ foo.cpp
foo.cpp: In member function ‘bool Foo::bar2(int)’:
foo.cpp:13:23: error: no matching function for call to ‘id(int&)’
return id<bar>(arg);
^
foo.cpp:13:23: note: candidate is:
foo.cpp:2:6: note: template<bool (& func)(int)> bool id(int)
bool id(int arg) {
^
foo.cpp:2:6: note: template argument deduction/substitution failed:
foo.cpp:13:23: error: could not convert template argument ‘Foo::bar’ to ‘bool (&)(int)’
return id<bar>(arg);
^
But if instead I move bar to toplevel, as in
template<bool (&func)(int arg)>
bool id(int arg) {
return func(arg);
}
bool bar(int arg) { return true; }
class Foo {
public:
Foo() {};
virtual ~Foo() {};
bool bar2(int arg) {
return id<bar>(arg);
};
};
int main() {
return 0;
}
it compiles fine. Why does this happen, and how can I fix it without making bar a global?
Note: In my original code, I was getting "(not const-qualified) cannot be initialized with a value of type" errors: (with icpc
)
CollisionWorld.cpp(73): error: a reference of type "bool (&)(const Line &, vec_dimension={double}, vec_dimension={double}, vec_dimension={double}, vec_dimension={double})" (not const-qualified) cannot be initialized with a value of type "bool (const Line &, vec_dimension={double}, vec_dimension={double}, vec_dimension={double}, vec_dimension={double})"
QuadTree<Line, vec_dimension, line_inside_box_with_time> *quad_tree =
^
(with g++
)
CollisionWorld.cpp:73:58: error: could not convert template argument ‘CollisionWorld::line_inside_box_with_time’ to ‘bool (&)(const Line&, double, double, double, double)’
QuadTree<Line, vec_dimension, line_inside_box_with_time> *quad_tree =
^
The problem is that the template expects a free function, not a member funciton. That is why it works when you put bar() out of Foo,
Try it like this:
template<typename C, bool (C::*func)(int arg)>
bool id(C *mthis, int arg) {
return (mthis->*func)(arg);
}
class Foo {
public:
Foo() {};
virtual ~Foo() {};
bool bar(int arg) { return true; }
bool bar2(int arg) {
return id<Foo, &Foo::bar>(this, arg);
};
};
To call a member function, you need two things: the this
pointer and the function. Therefore it is not possible as easy as you write it. id
would need the this
pointer!
The template definition would look like this:
template<bool (Foo::*func)(int)>
But still, you cannot implement a true id
function that works both on functions and member functions.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.