#include <iostream>
template<typename Impl>
struct renderer{
void get(){
static_cast<Impl*>(this)->get();
}
};
struct open_gl : public renderer<open_gl>{
void get(){
std::cout << "OpenGL" << std::endl;
}
};
struct direct_draw : public renderer<direct_draw>{
void get(){
std::cout << "DX" << std::endl;
}
};
template<typename T>
void print_renderer(renderer<T> r){
r.get();
}
int main() {
auto gl = open_gl();
auto dx = direct_draw();
print_renderer(gl);
print_renderer(dx);
}
Why can't I change the parameter of print_renderer to void
print_renderer(const renderer<T> &r)?
cannot convert 'this' pointer from 'const renderer<open_gl>' to 'renderer<open_gl> &'
`
Why do I get a runtime error when I rename the method get in open_gl from
get to get1? Shouldn't this trigger a compiler error? Error = Stack overflow
**Note I am using the latest MSVC
1) Because get is not a const member function : it cannot make the promise of not modify your (const) argument.
You could declare get as const, and it compiles fine :
void get() const { ... }
2) The base get method will be called, going into infinite recursion : Stack Overflow.
If you declare your function override (it needs to be virtual), the compiler will throw an error if it does not indeed override a base method :
void get1() override { ... } // Compiler error
void get() override { ... } // Ok
Note:
The title is "Static polymorphism in C++", but I think that you misunderstood what is static polymorphism : it does not (have to) make use of inheritance (as you did). Rather, the templates compile-time duck typing will statically "resolve" function calls for you.
That is, you don't need related types, you don't need the base renderer class at all, and you can simply do the following (in which case, renaming to get1 will cause a compiler error) :
#include <iostream>
struct open_gl {
void get(){
std::cout << "OpenGL" << std::endl;
}
};
struct direct_draw {
void get(){
std::cout << "DX" << std::endl;
}
};
template<typename T>
void print_renderer(T r){
r.get();
}
int main() {
auto gl = open_gl();
auto dx = direct_draw();
print_renderer(gl);
print_renderer(dx);
}
Live demo
Becuase get is not marked const.
Because the base class method is used (irrelevantly of cast), and it goes into infinite loop.
Related
I want to pass pointers of some functions to a template class to use them later. I was wondering if:
Does it make a possibly (speed-wise) beneficial difference if I make these functions inline?
Functions themselves are possibly one line wrapper for another functions like the example below:
//inline ?
void func_wrapper_1(){
func1(arg1);
}
//inline ?
void func_wrapper_2(){
func2(arg2);
}
and the class template is like the example below:
template<void(*f1)(), void(*f2)()>
class caller{
public:
static void func(int v){
if(v) {
(*f1)();
}else{
(*f2)();
}
}
};
And later on in the main function it will be used like the example below:
caller<func_wrapper_1,func_wrapper_2>::func(0);
caller<func_wrapper_1,func_wrapper_2>::func(1);
I know that every things depends on compiler and compiling option, but lets assume compiler accepts to make these functions inline.
Whether or not a compiler will be smart enough to inline a given situation is up for grabs but I think it may be possible by creating Callable Types by overloading the function call operator.
Something like this:
template<typename Func1, typename Func2>
class caller{
public:
static void func(int v){
if(v) {
// Func1() - creates an object of type Func1
// that object is 'called' using the '()' operator
Func1()();
}else{
Func2()();
}
}
};
struct CallableType1
{
// overloading the function call operator makes objects of
// this type callable
void operator()() const { std::cout << "callable 1" << '\n'; }
};
struct CallableType2
{
void operator()() const { std::cout << "callable 2" << '\n'; }
};
int main()
{
caller<CallableType1, CallableType2> cc;
cc.func(2);
}
I am trying a sort of type-erasure with some function pointers and templates as given in the example below. What I find strange is with GCC i get wrong result where as with VS 2017, I get the expected one. So, who is correct and who is wrong and why ?
Live example on COLIRU: http://coliru.stacked-crooked.com/a/225db5711c07c8b0
struct A { void PrintA() { std::cout << "Event A" << std::endl; } };
struct B { void PrintB() { std::cout << "Event B" << std::endl; } };
struct C { void PrintC() { std::cout << "Event C" << std::endl; } };
struct RunBase
{
virtual void operator()() = 0;
};
template <typename T>
struct Run : public RunBase
{
using FUNC = void (T::*)();
Run(T& o, FUNC&& f) : mObj(o), mFunc(f) {}
void operator()() override { (mObj.*mFunc)(); }
T& mObj;
FUNC& mFunc;
};
int main()
{
A a;
B b;
C c;
std::vector<std::unique_ptr<RunBase> > mFuncs;
mFuncs.push_back(std::make_unique<Run<A> >(a, &A::PrintA));
mFuncs.push_back(std::make_unique<Run<B> >(b, &B::PrintB));
mFuncs.push_back(std::make_unique<Run<C> >(c, &C::PrintC));
for (auto& i : mFuncs)
(*i)();
return 0;
}
Expected result:
Event A
Event B
Event C
But GCC gives me:
Event C
Event C
Event C
It's because you store a reference inside your object, but &A::PrintA etc. are temporaries which are destroyed at the end of the full expression, and so the member reference is left dangling, and its use results in undefined behaviour.
Simply store a copy of the member function pointer to fix it:
FUNC mFunc;
PS. When mFuncs is destroyed, the unique pointers delete child objects through a base pointer. The behaviour is undefined unless you declare RunBase::~RunBase virtual.
So, who is correct and who is wrong and why ?
Your program is wrong; There is no correct behaviour for it.
I have a scope guard like class (this is the simplified test case):
template<void(*close)()>
struct Guard1
{
template<typename O>
Guard1(O open) { open(); }
~Guard1() { close(); }
};
void close() { std::cout << "close g1\n"; }
int main()
{
Guard1<close> g1 = [](){ std::cout << "open g1\n"; };
}
I modified it such that the close expression can also be given as a lambda:
class Guard2
{
std::function<void()> close;
public:
template<typename O, typename C>
Guard2(O open, C close) : close(close)
{
open();
}
~Guard2() { close(); }
};
int main()
{
Guard2 g2(
[](){ std::cout << "open g2\n"; },
[](){ std::cout << "close g2\n"; });
}
However I had to introduce an extra field const std::function<void()>& close; to pass the lambda from the constructor to the destructor.
Is there a way to avoid this extra field while still keeping the lambda (and a nice syntax when used as well)?
Since you want to use it only as ScopeGuard - then you can be sure that const reference or rvalue reference to your close() are valid. You need a member or base class as in other answer - but this is not very big difference. But you can have it as rvalue reference to your lambda, not to std::function which is of quite big performance cost:
template <class Close>
class ScopeGuard {
public:
template <typename Open>
ScopeGuard(Open&& open, Close&& close)
: close(std::forward<Close>(close))
{
open();
}
ScopeGuard(ScopeGuard&& other) : close(std::move(other.close))
{}
~ScopeGuard()
{
close();
}
private:
Close&& close;
};
To make it easier to use - have this make function:
template <class Open, class Close>
auto makeScopeGuard(Open&& open, Close&& close)
{
return ScopeGuard<Close>(std::forward<Open>(open),
std::forward<Close>(close));
}
And usage:
#include <iostream>
using namespace std;
int main()
{
int i = 0;
auto scope = makeScopeGuard([&i]{cout << "Open " << i++ << "\n";},
[&i]{cout << "Close " << i++ << "\n";});
cout << "Body\n";
}
Output:
Open 0
Body
Close 1
I verified it works for gcc and clang, C++14 without errors/warnings.
It's generally not possible. Unlike a function pointer, a lambda can capture and therefore contain run-time state. True, your lambda does not, and therefore can be converted to a function pointer, but that doesn't make it a template argument.
If you can accept a bit of cheating: stuff the lambda into a base class instead of a field:
#include <iostream>
template<typename Base>
struct Guard1 : public Base
{
template<typename O>
Guard1(O open, Base base ) : Base(base) { open(); }
Guard1(Guard1 const& rhs) : Base(static_cast<Base const&>(rhs)) { }
~Guard1() { (*this)(); }
};
template<typename O, typename C>
Guard1<C> makeGuard(O o, C c) { return Guard1<C>(o,c); }
int main()
{
auto g1 = makeGuard([](){ std::cout << "open g1\n"; },
[](){ std::cout << "close g1\n"; } );
}
Is there a way to avoid this extra field while still keeping the lambda (and a nice syntax when used as well)?
Yes: If you observe, there is nothing to be gained by passing the open function to your scope guard (therefore the Single Responsibility Principle states you should not have it there).
You should also pass the function as a runtime parameter, not a template parameter. This will allow for more natural syntax in client code.
You should make the type independent on the template type. This will also make for more natural syntax in client code.
You should ensure the destructor does not throw.
class Guard final
{
public:
Guard1(std::function<void()> at_scope_exit)
: f_(std::move(at_scope_exit))
{
}
~Guard1() noexcept { try{ f_(); } catch(...) {} }
private:
std::function<void()> f_;
};
Your client code should then look like this:
int x()
{
operation.begin_transaction();
Guard commit{ [&operation](){ operation.commit_transaction(); } };
// do things & stuff here
}
Maybe you can use the answer of this question.
Hope I am not wrong, but if it was possible to use the constructor's pointer, you could pass it to type_traits (look at the first answer in that question), and get the second argument which would be close function, and then you could alias it.
Since it is not possible to get the constructor's pointer, maybe you can use an other member function to initialize your object ?
A reference to array parameter is useful because it prevents decay, allowing you to deduce the size of an array.
template <typename T, std::size_t N>
constexpr std::size_t array_size(T (&) [N]) noexcept
{
return N;
}
But when is this useful?
template<typename T>
void foo(T& t)
{
// we now have a reference to bar
}
void bar() { }
int main()
{
foo(bar);
}
When do we care about preventing function to pointer decay? I'm asking about when this is useful, not why it isn't disallowed.
Like with objects, we us a pointer if “no object” (“no function”) is a sensible value and a reference if we wish to make sure that (unless somebody insists to shoot himself in the foot) there is always a valid object (function) referred to.
Consider the following poor man's function wrapper (wealthy man goes over there).
template<typename>
class Function; // never defined
template<typename ReturnT, typename... ArgT>
class Function<ReturnT(ArgT...)>
{
private:
ReturnT (*func_)(ArgT...);
public:
// Will also accept a 'nullptr'
Function(ReturnT (*func)(ArgT...)) noexcept : func_ {func}
{
}
ReturnT
operator()(ArgT... args)
{
return this->func_(args...);
}
};
Now we can write the following program, which works just fine.
#include <iostream>
int
add(int a, int b)
{
return a + b;
}
int
main()
{
Function<int(int, int)> f {add}; // ok
std::cout << f(5, 7) << std::endl; // ok, prints 12
}
However, we can also write the following program, which doesn't work so nice.
int
main()
{
Function<int(int, int)> f {nullptr}; // compiles fine
std::cout << f(5, 7) << std::endl; // compiles fine, crashes at run-time
}
Instead, if we had replaced the (*func) with (&func) in the template's definition,
// Won't accept a 'nullptr'
Function(ReturnT (&func)(ArgT...)) noexcept : func_ {func}
{
}
the line
Function<int(int, int)> f {nullptr}; // compile-time error
would have triggered a compile-time error.
To me the difference is like between normal variable reference and a pointer. References are nicer to deal with than pointers.
I had a use-case when I to customize a parts of an algorithm. It had some phases and I could switch between several options for each phase. This is of course achievable with pointers, but hey, you can use pointers instead of references pretty much everywhere too.
It looked similar to this:
#include <iostream>
using namespace std;
class Foo
{
public:
Foo(void(&t)()) : barish(t) { };
void fun() {barish();};
private:
void(&barish)();
};
void bar() { cout << "meow\n";}
void bark() { cout << "woof\n";}
int main()
{
Foo foo1(bar);
Foo foo2(bark);
foo1.fun();
foo2.fun();
}
You can customize fun and don't have to deal with dereferencing and asserts that it's not null.
Consider the following class structure:-
class foo {
public:
int fun () {
cout << "in foo" << endl;
}
};
class bar_class1:public foo {
public:
int fun () {
cout << "in bar_class1" << endl;
}
};
class bar_class2:public foo {
public:
float fun () {
cout << "in bar_class2" << endl;
}
};
main () {
foo * foo_pointer = new bar_class1();
foo_pointer->fun();
}
The output of the above program is in foo. Is there a way, that using a pointer of type foo * which actually points to an object of type bar_class1 or bar_class2, we can call the fun function of the derived class instead of the base class? I am not able to make the fun function virtual in the base class foo since, then there is a return type conflict for function foo in the derived class bar_class2.
Here's my comments as an answer.
You cannot do that.
If that kind of polymorphism were possible, wouldn't that break horribly when code calls foo::fun (expecting an int) on an object whose actual type is bar_class2 and thus gets a float? Do you want to simply throw away type safety?
If you want different return types, sounds like you want a template. But you cannot use templates quite in the way that you want to use foo(). Static polymorphism (templates) and run time polymorphism (late binding) don't mix well. You need to redesign your oop structure.
If you absolutely hate type safety, you can sort of do this with void pointers. But for the love of Flying Spaghetti Monster, don't ever do this in c++. Please close your eyes before reading the following code to avoid exposure.
#include <iostream>
class foo {
public:
virtual void* fun() = 0;
virtual ~foo(){};
};
class bar_class1: public foo {
public:
void* fun() {
return &value;
}
private:
int value = 1;
};
class bar_class2: public foo {
public:
void* fun() {
return &value;
}
private:
float value = 1.1;
};
int main() {
foo* foo_pointer1 = new bar_class1();
foo* foo_pointer2 = new bar_class2();
// in c++ compiler must know the type of all objects during compilation
std::cout << *reinterpret_cast<int*>(foo_pointer1->fun()) << '\n';
std::cout << *reinterpret_cast<float*>(foo_pointer2->fun()) << '\n';
delete foo_pointer1;
delete foo_pointer2;
}
Perhaps similar to the existing answer, I really hope you realize changing your design is better than this mess, but I believe it's the best you're going to get. I force you to specify the return type at the callsite (e.g., someFoo->fun<int>()), since you're going to have to know it anyway, and dispatch based on that. Any funny business and you'll get an exception. Also keep in mind the performance of this is, I imagine, less than desirable.
#include <cassert>
#include <stdexcept>
#include <type_traits>
struct foo {
virtual ~foo() = default;
template<typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type, typename = void>
T fun();
template<typename T, typename = typename std::enable_if<std::is_same<T, float>::value>::type>
T fun();
};
struct bar_class1 : foo {
int fun() {
return 2;
}
};
struct bar_class2 : foo {
float fun() {
return 3.5f;
}
};
template<typename T, typename, typename Dummy>
T foo::fun() {
if (auto *p = dynamic_cast<bar_class1 *>(this)) {
return p->fun();
} else if (dynamic_cast<bar_class2 *>(this)) {
throw std::invalid_argument("Mismatching dynamic type.");
} else {
return 1;
}
}
template<typename T, typename>
T foo::fun() {
auto *p = dynamic_cast<bar_class2 *>(this);
if (dynamic_cast<bar_class1 *>(this) || !p) {
throw std::invalid_argument("Mismatching dynamic type.");
} else if (auto *p = dynamic_cast<bar_class2 *>(this)) {
return p->fun();
}
assert(false); //should never get here, but compiler doesn't know that
}
If you'd like the main function, I've written a complete sample.
To answer your question: No, late binding isn't possible without deciding the return type. ...at least not in a reasonable manner, see user2079303's great counter-example. But...
you may change your code (for example) into something like the following, using the keyword virtual and equalize the return type for instance to void:
class foo
{
public:
virtual void fun(std::ostream& out) {
out << "in foo" << std::endl;
}
};
so you can decide the output type later:
class intFoo: public foo
{
public:
void fun(std::ostream& out) {
// output an int
out << "in bar_class1. data: " << data << endl;
}
int data;
};
class floatFoo: public foo
{
public:
void fun(std::ostream& out) {
// output a float
out << "in bar_class2. data: " << data << endl;
}
float data;
};
For brevity, I double-use the output stream - now a parameter of the function fun() - function to demonstrate type-dependent portion of your derived class. In your application, the parameter will probably be of another, more useful type.
The function fun is not a virtual function since you didn't use the keyword "virtual" to decorate it. So, the compile will determine which function to call at compiling time. So, there is no way to tell the compiler to call another function because the compiler will use its static type, i.e. the variable definition type -- foo *.