I have looked at several similar questions on SO. Maybe I am not grokking the solutions there. In those questions when the return type is auto or templated then separating declaration and definition in two different units causes a failure in compilation. This can be solved by explicitly declaring a concrete signature for the function definition. In my case I am not sure how to do that.
My scenario is as below:
// api.h
template <typename TImpl>
concept IsAProcessor = requires(TImpl impl)
{
impl.init();
impl.process();
impl.deinit();
};
enum UseCase {
USECASE1,
USECASE2
};
template <IsAProcessor TImpl>
void Process(TImpl& impl)
{
impl.process();
}
class Engine
{
public:
IsAProcessor auto getInstance(UseCase a);
};
// End - api.h
// api.cpp
#include "api.h"
#include "third_party.h"
IsAProcessor auto Engine::getInstance(UseCase a) {
switch (UseCase) {
case USECASE1:
return UseCase1Impl(); // Defined in third_party.h and satisfies concept requirement.
case USECASE2:
return UseCase2Impl();
}
}
// End - api.cpp
// third_party.h
class UseCase1Impl {
public:
void init(void);
void process(void);
void deinit(void);
}
// End - third_party.h
// third_party.cpp
#include "third_party.h"
void UseCase1Impl::init(void) {...};
// and so forth
// End - third_party.cpp
// User code
#include "api.h"
{
auto en = Engine();
auto usecase = en.getInstance(UseCase::USECASE1);
//^^^ cannot be used before it is defined here
Process(usecase);
}
As I mentioned in the question, it is not desirable to expose UseCase1Impl and UseCase2Impl. How do I get past the error: function 'getInstance' with deduced return type cannot be used before it is defined
The return type of a function is a static property, it can't change based on runtime data.
If you can, lift UseCase to a template parameter, and use if constexpr to have exactly one active return for each instantiation.
template<UseCase a>
auto Engine::getInstance() {
if constexpr (a == USECASE1)
return UseCase1Impl(); // Defined in third_party.h and satisfies concept requirement.
if constexpr (a == USECASE2)
return UseCase2Impl();
}
If you can't do that, you will have to find a common type to return.
struct IProcessor
{
virtual ~IProcessor() = default;
virtual void init() = 0;
virtual void process() = 0;
virtual void deinit() = 0;
};
template <IsAProcessor T>
class ProcessorFacade : public IProcessor
{
T impl;
public:
template <typename... Args>
ProcessorFacade(Args&&... args) : impl(std::forward<Args>(args)...) {}
void init() final { impl.init(); }
void process() final { impl.process(); }
void deinit() final { impl.deinit(); }
};
std::unique_ptr<IProcessor> Engine::getInstance(UseCase a) {
switch (UseCase) {
case USECASE1:
return std::make_unique<ProcessorFacade<UseCase1Impl>>();
case USECASE2:
return std::make_unique<ProcessorFacade<UseCase2Impl>>();
}
}
Related
I have
class ClassA {};
class ClassB {};
auto func_a() -> ClassA {
return ClassA(); // example implementation for illustration. in reality can be different. does not match the form of func_b
}
auto func_b() -> ClassB {
return ClassB(); // example implementation for illustration. in reality can be different. does not match the form of func_a
}
I want to be able to use the syntax
func<ClassA>() // instead of func_a()
func<ClassB>() // instead of func_b()
(this is as part of a bigger template)
but I don't know how to implement this template specialization for the function alias.
Help? What is the syntax for this?
[Edit] The answers posted so far do not answer my question, so I'll edit my question to be more clear.
The actual definition of func_a and func_b is more complex than just "return Type();". Also they cannot be touched. So consider them to be
auto func_a() -> ClassA {
// unknown implementation. returns ClassA somehow
}
auto func_b() -> ClassB {
// unknown implementation. returns ClassB somehow
}
I cannot template the contents of func_a or func_b. I need the template for func<ClassA|ClassB> to be specialized for each one of the two and be able to select the correct one to call
You might do something like (c++17):
template <typename T>
auto func()
{
if constexpr (std::is_same_v<T, ClassA>) {
return func_a();
} else {
return func_b();
}
}
Alternative for pre-C++17 is tag dispatching (which allows customization point):
// Utility class to allow to "pass" Type.
template <typename T> struct Tag{};
// Possibly in namespace details
auto func(Tag<ClassA>) { return func_a(); }
auto func(Tag<ClassB>) { return func_b(); }
template <typename T>
auto func() { return func(Tag<T>{}); }
You can do it like this :
#include <iostream>
#include <type_traits>
class A
{
public:
void hi()
{
std::cout << "hi\n";
}
};
class B
{
public:
void boo()
{
std::cout << "boo\n";
}
};
template<typename type_t>
auto create()
{
// optional : if you only want to be able to create instances of A or B
// static_assert(std::is_same_v<A, type_t> || std::is_same_v<B, type_t>);
type_t object{};
return object;
}
int main()
{
auto a = create<A>();
auto b = create<B>();
a.hi();
b.boo();
return 0;
}
I have a non-type template class template<std::size_t N> Derived<N> which derives from some non-template base class Base:
class Base
{
public:
double some_value;
// Some methods and variables that do not depend on N
// I wish to keep these in a non-templated class
virtual const size_t get_N() = 0;
virtual ~Base() = default;
Base(double value): some_value {value} {};
};
template <std::size_t N>
class Derived: public Base
{
public:
double some_other_value;
// Some functions and variables, for which
// the types and actions depend on N
const size_t get_N() override
{
return N;
}
Derived(double value1, double value2): Base(value1), some_other_value {value2} {};
};
Now I have a function call_by_base(Base& my_base), which only uses member variables/functions declared in Base. The only exception to this, is a call to template<std::size_t N> void call_by_derived(Derived& my_derived). Since almost the entire function call_by_base is independent of the template parameter, I would prefer to keep this function non-templated.
I tried to achieve the above with implementations along the lines of:
template<std::size_t N>
void call_by_derived(Derived<N>& my_derived)
{
std::cout << "in call_by_derived" << std::endl;
// Methods that use the functions and variables in Derived.
}
void broken_call_by_base(Base& my_base)
{
std::cout << "in call_by_base" << std::endl;
// Manipulations independent of child
// type Derived<N>
auto derived = dynamic_cast<Derived<my_base.get_N()>&>(my_base);
call_by_derived(derived);
// Manipulations independent of child
// type Derived<N>
}
When I try to compile this code, I get error: expression ‘Base::get_N’ is not a constant-expression. I tried to resolve this error by trying to change different thing, both in my Base and Derived class. This was all without success.
I managed to get the following alternative to work:
void working_call_by_base(Base& my_base)
{
std::cout << "in call_by_base" << std::endl;
if(my_base.get_N()==2)
{
auto derived = dynamic_cast<Derived<2>&>(my_base);
call_by_derived(derived);
}
if(my_base.get_N()==3)
{
auto derived = dynamic_cast<Derived<3>&>(my_base);
call_by_derived(derived);
}
}
This is however very tedious, especially when N can take on many more values. Is there any way to get a function along the lines of broken_call_by_base working? That is: How can I downcast a non-template Base to a non-type template Derived<N>?
ps. Only object of the Derived<N> type will be created. This is the code in main to test:
int main()
{
Derived<3> test(1.0,2.0);
working_call_by_base(test);
broken_call_by_base(test);
call_by_derived(test);
}
It'll be best if you can use a virtual member function to avoid the if/else checks.
If that is not an option for some reason, use of a callback/plugin mechanism is the most appropriate.
You provide a mechanism in the Base-specific code base to allow other classes/functions/modules to register functions that are appropriate for the type they know about.
In the Base-specific code, you keep track of the registered functions using a key that is appropriate for Base.
In the Base-specific code, you check whether a function has been registered for the key. If it has, you call the function with the suitable arguments.
In the derived class specific code, you can downcast to the appropriate class. If the downcast succeeds, in most cases it should, you proceed to use the derived class.
This pattern strictly adheres to the Open-Closed Principle and is one of my favorite coding patterns.
In your case, the key is N.
Here's an example program that demonstrates the concept.
#include <iostream>
// Base.hpp
// #pragma once
#include <cstdint>
class Base
{
public:
double some_value;
// Some methods and variables that do not depend on N
// I wish to keep these in a non-templated class
virtual const size_t get_N() = 0;
virtual ~Base() = default;
Base(double value): some_value {value} {};
typedef void (*CallbackFunctionType1)(Base& b);
static void registerCallback(std::size_t N, CallbackFunctionType1 f);
};
void call_by_base(Base& my_base);
// Base.cpp
#include <map>
namespace BaseNS
{
using CallbackFunctionType1Map = std::map<std::size_t, Base::CallbackFunctionType1>;
CallbackFunctionType1Map& getCallbackFunctionType1Map()
{
static CallbackFunctionType1Map theMap;
return theMap;
}
}
void Base::registerCallback(std::size_t N, CallbackFunctionType1 f)
{
BaseNS::CallbackFunctionType1Map& theMap = BaseNS::getCallbackFunctionType1Map();
theMap[N] = f;
}
void call_by_base(Base& my_base)
{
std::cout << "In call_by_base" << std::endl;
BaseNS::CallbackFunctionType1Map& theMap = BaseNS::getCallbackFunctionType1Map();
BaseNS::CallbackFunctionType1Map::iterator iter = theMap.find(my_base.get_N());
if ( iter != theMap.end() )
{
iter->second(my_base);
}
}
// Derived.hpp
// #pragma once
template <std::size_t N>
class Derived: public Base
{
public:
double some_other_value;
// Some functions and variables, for which
// the types and actions depend on N
const size_t get_N() override
{
return N;
}
Derived(double value1, double value2): Base(value1), some_other_value {value2} {};
};
// Derived.cpp
// Register call back functions for Derived.
namespace DerivedNS
{
template <std::size_t N>
void call_by_derived(Derived<N>& derived)
{
std::cout << "In call_by_derived<" << N << ">" << std::endl;
// Use derived.
}
template <std::size_t N>
void call_for_derived(Base& my_base)
{
Derived<N>* d_ptr = dynamic_cast<Derived<N>*>(&my_base);
if ( d_ptr != nullptr )
{
call_by_derived(*d_ptr);
}
else
{
// Error.
}
}
bool registerCallbackFunctions()
{
// Register callbacks for as many values of N as needed.
Base::registerCallback(1, call_for_derived<1>);
Base::registerCallback(2, call_for_derived<2>);
Base::registerCallback(3, call_for_derived<3>);
Base::registerCallback(4, call_for_derived<4>);
Base::registerCallback(5, call_for_derived<5>);
return true;
}
bool dummy = registerCallbackFunctions();
}
int main()
{
Derived<1> d1(0, 0);
Derived<2> d2(0, 0);
Derived<10> d3(0, 0);
call_by_base(d1);
call_by_base(d2);
call_by_base(d3); // Does not go to call_by_derived.
}
Output:
In call_by_base
In call_by_derived<1>
In call_by_base
In call_by_derived<2>
In call_by_base
I'm trying to implement a callback which passes control from an Interrupt Service Routine to a member function on a c++ class. I thought lambdas and closures would be a convenient means of doing this, but I'm having trouble implementing it. Below is a simplified version of my code.
The issue I'm stuck on is how to store the "function pointer" to the "lambda".
class Gpio
{
public:
typedef void (*ExtiHandler)();
private:
ExtiHandler handler;
public:
void enable_irq(ExtiHandler handler_in)
{
// enable interrupt
// ...
// save handler so callback can be issued later
handler = handler_in;
}
};
class Button
{
private:
Gpio& pin;
public:
Button(Gpio& pin_in) : pin(pin_in)
{
};
void button_pressed()
{
// do something
}
void init()
{
pin.enable_irq([this]() { this->button_pressed(); });
}
};
Compiling fails with the following error message;
no matching function for call to 'Gpio::enable_irq(Button::init()::<lambda()>)'candidate: void Gpio::enable_irq(Gpio::ExtiHandler) no known conversion for argument 1 from 'Button::init()::<lambda()>' to 'Gpio::ExtiHandler {aka void (*)()}' Build failed
How can I modify this code to resolve the compile error?
The problem is, that enable_irq function expects a typed function pointer of type void (*ExtiHandler)() not a lambda function.
That means, here
pin.enable_irq([this]() { this->button_pressed(); });
you are trying to store a lambda function(with capturing the instance) to a typed function pointer. You could have converted the lambda to a function pointer(easily) if it would have been a capture-less lambda.
See [expr.prim.lambda.closure] (sec 7)
The closure type for a non-generic lambda-expression with no
lambda-capture whose constraints (if any) are satisfied has a
conversion function to pointer to function with C++ language linkage
having the same parameter and return types as the closure type's
function call operator.
Since lambdas are not just ordinary functions and capturing it need to preserve a state,
you can not find any simple or conventional solution to make them assign to function pointers.
Solution - 1
The simplest solution is to use std::function instead, by paying some type erasure overhead. That means, in your code, just need to change the
typedef void(*ExtiHandler)();
to
typedef std::function<void()> ExtiHandler;
// or
// using ExtiHandler = std::function<void()>;
Solution - 2
Can this be accomplished without using the STL?
Yes. After making a small research on this topic, I came up with a type traits solution to store the lambdas with closure to the equivalent typed function pointer.
#include <iostream>
template<typename Lambda> struct convert_lambda : convert_lambda<decltype(&Lambda::operator())> {};
template<typename Lambda, typename ReType, typename... Args>
struct convert_lambda<ReType(Lambda::*)(Args...) const>
{
using funPtr = ReType(*)(Args...);
static funPtr make_function_ptr(const Lambda& t)
{
static const Lambda& lmda = t;
return [](Args... args) { return lmda(args...); };
}
};
template<typename Lambda> using convert_lambda_t = typename convert_lambda<Lambda>::funPtr;
template<typename Lambda> constexpr convert_lambda_t<Lambda> make_function_ptr(const Lambda& t)
{
return convert_lambda<Lambda>::make_function_ptr(t);
}
Usage: SEE LIVE EXAMPLE
You can now simply continue with your Gpio and Button classes, without
changing anything.:
pin.enable_irq(make_function_ptr([this]() { this->button_pressed(); }));
// or
// pin.enable_irq(make_function_ptr([&]() { this->button_pressed();}));
Or with arguments. For example
int aa = 4;
auto lmda = [&aa](const int a, const float f) { std::cout << a * aa * f << std::endl; };
void(*fPtrTest)(const int, const float) = make_function_ptr(lmda);
fPtrTest(1, 2.0f);
Drawbacks: The solution - 2:
is not capable of recognizing the optional sequence of specifiers.(i.e, mutable, constexpr)
is not capable of forwarding parameter pack to the traits. i.e,
the following is not possible:
return [](Args&&... args) { return lmda(std::forward<Args>(args)...); };
Closure object can be assigned to function pointer only if capture list of lambda is empty, in your case this condition is not met - [this].
You can use std::function as wrapper to store your closures:
#include <functional>
class Gpio
{
public:
using ExtiHandler = std::function<void()>;
private:
std::function<void()> handler;
public:
void enable_irq(const ExtiHandler& handler_in)
{
handler = handler_in;
}
};
If you don't have std library then you could implement the type erasure yourself.
Something like this ...
#include <iostream>
#include <memory>
struct function
{
struct base
{
virtual void call() = 0;
virtual base* clone() = 0;
};
template <typename Fn>
struct impl : base
{
Fn fn_;
impl(Fn&& fn) : fn_(std::forward<Fn>(fn)){}
impl(Fn& fn) : fn_(fn){}
virtual void call()
{
fn_();
}
virtual base* clone() { return new impl<Fn>(fn_); }
};
base* holder_;
function() : holder_(nullptr)
{};
template <typename Fn>
function(Fn&& fn) : holder_(nullptr)
{
holder_ = new impl<Fn>(std::forward<Fn>(fn));
}
function( function&& other)
{
holder_ = other.holder_;
other.holder_ = nullptr;
}
function(const function& other)
{
holder_ = other.holder_->clone();
}
~function()
{
if (holder_) delete holder_;
}
function& operator=(function&& other)
{
if (holder_) delete holder_;
holder_ = other.holder_;
other.holder_ = nullptr;
return *this;
}
function& operator=(const function& other)
{
if (holder_) delete holder_;
holder_ = other.holder_->clone();
return *this;
}
void operator()()
{
holder_->call();
}
};
class Gpio
{
public:
using ExtiHandler = function;
//private:
ExtiHandler handler;
//public:
void enable_irq(ExtiHandler handler_in)
{
// enable interrupt
// ...
// save handler so callback can be issued later
handler = handler_in;
}
};
class Button
{
private:
Gpio& pin;
public:
Button(Gpio& pin_in) : pin(pin_in)
{
};
void button_pressed()
{
std::cout << "Button pressed" << std::endl;
}
void init()
{
pin.enable_irq([this]() { this->button_pressed(); });
}
};
int main() {
Gpio some_pin;
Button b(some_pin);
b.init();
some_pin.handler();
return 0;
}
Demo
I'd like to fill in the store() and launch() methods in the below code. The important detail which captures the spirit of the problem is that the object foo declared in main() no longer exists at the time we call launch(). How can I do this?
#include <cstdio>
#include <cstring>
#include <type_traits>
template<typename T, typename U=
typename std::enable_if<std::is_trivially_copyable<T>::value,T>::type>
struct Launchable {
void launch() { /* some code here */ }
T t;
// other members as needed to support DelayedLauncher
};
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
// copy-construct/memcpy t into some storage
}
void launch() const {
// call t.launch(), where t is (a copy of) the last value passed into store()
}
// other members as needed
};
int main() {
DelayedLauncher launcher;
{
Launchable<int> foo;
launcher.store(foo);
}
launcher.launch(); // calls foo.launch()
return 0;
}
Note that if we only had a fixed set of N types to pass into store(), we could achieve the desired functionality by declaring N Launchable<T> fields and N non-template store() methods, one for each type, along with an enum field whose value is use in a switch statement in the launch() method. But I'm looking for an implementation of DelayedLauncher that will not need modification as more Launchable types are added.
using std::function:
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
f = [t]() {t.launch();};
}
void launch() const { f(); }
private:
std::function<void()> f;
};
You could give Launchable a base class with a virtual launch() and no template, and store pointers to that base class in Launcher::store.
EDIT: Adapted from #dshin's solution:
struct LaunchableBase {
virtual void launch() = 0;
};
template<typename T, typename U=
typename std::enable_if<std::is_trivially_copyable<T>::value,T>::type>
struct Launchable : public LaunchableBase {
virtual void launch() override { /* some code here */ }
T t;
// other members as needed to support DelayedLauncher
};
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
static_assert(sizeof(t) <= sizeof(obj_buffer),
"insufficient obj_buffer size");
static_assert(std::is_trivially_destructible<T>::value,
"leak would occur with current impl");
p = new (obj_buffer) Launchable<T>(t);
}
void launch() const {
p->launch();
}
private:
char obj_buffer[1024]; // static_assert inside store() protects us from overflow
LaunchableBase *p;
};
I believe this variant of Jarod42's solution will avoid dynamic allocation, although I would appreciate if someone could confirm that this will work the way I think it will:
class DelayedLauncher {
public:
template<typename T>
void store(const Launchable<T>& t) {
static_assert(sizeof(t) <= sizeof(obj_buffer),
"insufficient obj_buffer size");
static_assert(std::is_trivially_destructible<T>::value,
"leak would occur with current impl");
auto p = new (obj_buffer) Launchable<T>(t);
auto ref = std::ref(*p);
f = [=]() {ref.get().launch();};
}
void launch() const {
f();
}
private:
char obj_buffer[1024]; // static_assert inside store() protects us from overflow
std::function<void()> f;
};
I believe it should work because the resources I've looked at indicate that std::function implementations typically have a "small capture" optimization, only triggering a dynamic allocation if the total size of the captured data exceeds some threshold.
EDIT: I replaced my code with a version provided by Jarod42 in the comments. The standard guarantees the above implementation will not trigger dynamic allocation.
I need to instantiate a free template function (FTF) within a template class (TC). The FTF takes as a template parameter one of the template parameters of the TC. The TC also holds generic pointers to these FTF's, and these functions are called through the pointers.
The step of taking a pointer to a FTF is not enough to instantiate it, and I receive linker errors from the GCC toolchain. MSDN illustrates FTF specification as so -- however my instantion of the FTF is dependant on a template parameter of my TC, and therefore the FTF instantiation cannot be placed in free scope.
Is this possible ? I am attaching some basic generated code, the issue is in the constructor of the class test_service, where I assign the pointer of a free function into a custom container. I get a linker error telling me the free function cannot be found (uninstantiated). I know that specifying a call to the template function in the class somewhere will produce a instantiation, however I am only going to be making a call via a pointer.
#include "rpc_common.h"
#include <boost/cstdint.hpp>
namespace rubble { namespace rpc {
struct test_service_dummy_tag{};
template<typename T>
class test_service_skel
{
public:
bool Init() {}
bool TearDown() {}
bool test_one(TestRequest,TestResponse){};
private:
};
template<typename T_IMPL>
bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
{
return 0;
}
template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
class test_service
{
public:
test_service()
{
// uncomment the following two lines and a instantiation will occur.
// ClientRequest cr;
//test_service_test_one<T_IMPL>(m_impl,cr);
m_dispatch_table.SetEntry( Oid("test_one",0),(void *) & test_service_test_one<T_IMPL>);
}
bool Init() { return m_impl.Init(); };
bool TearDown() { return m_impl.TearDown(); };
private:
T_IMPL m_impl;
OidContainer<Oid,void *> m_dispatch_table;
};
} }
EDIT: self-contained minimal version
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T>
bool test_function()
{
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = (void *) & test_function<T>;
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
There is no problem iff you don't use a void*, i.e.: http://www.ideone.com/eRgUG
However, if you insist on storing the pointer in a void*, then you need to take the address using a specific function pointer first and then cast - e.g.
bool (*temp)() = &test_function<T>;
dispatch = reinterpret_cast<void*>(temp); // YUCK
This gives the compiler enough context to generate the address for you.
Ahh - just saw DeadMG's answer, the function to generate the void* is neater...
Your self-contained example wouldn't compile for me with a strange error about overloaded functions, when there is no overloading going on, with MSVC. I did, however, manage to work around it.
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T> void* to_void_pointer(T t) {
return reinterpret_cast<void*>(t);
}
template<typename T>
bool test_function()
{
return true;
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = to_void_pointer(&test_function<T>);
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
This compiles cleanly. I suspect that whatever behaviour you're seeing and I saw is a compiler error.