Access class implementation instanciated from template parameter packs - c++

I would like to instantiate all States in the MachineT as a shared_ptr<T> then access them by typename.
In the following code, it refers to the instantiation (MachineT constructor) and a way to access the states (get function).
Is there any hashmap trick or a way to store in the class an "Index" information such as StateA::Index?
#include <memory>
#include <vector>
template <typename... States>
class MachineT {
public:
MachineT() {
states_.resize(sizeof...(States));
for (unsigned i = 0; i < states_.size(); ++i) {
// Instanciate states
// states_[i].reset(new decltype(State[i])());
}
}
~MachineT() {}
class State {
State(int state_id) : state_id_(state_id) {}
const size_t state_id_;
};
template<typename T>
std::shared_ptr<T> get() {
// Retrun the shared_ptr to the State
}
std::vector<std::shared_ptr<State>> states_;
};
struct StateA; // Forward declaration
struct StateB;
using StateMachine = MachineT<StateA, StateB>;
class StateA : StateMachine::State {};
class StateB : StateMachine::State {};
int main(int argc, char const* argv[]) {
StateMachine sm;
std::shared_ptr<StateA> state_a = sm.get<StateA>();
return 0;
}

It's perfectly doable. Here's how to do it in C++14:
#include <memory>
#include <tuple>
template <typename... States>
class MachineT {
public:
MachineT()
: states_{
std::make_shared<States>()...
} {
}
~MachineT() {}
template<typename T>
std::shared_ptr<T> get() {
return std::get<std::shared_ptr<T>>(states_);
}
std::tuple<std::shared_ptr<States>...> states_;
};
struct State1 {};
int main() {
MachineT<State1> a;
a.get<State1>();
}
Equivalent of std::get can be implemented with C++11 tools

Related

How to use a type defined and associated with a Template parameter in a class Template?

Below is an implementation of the above question.
#include <iostream>
#include <map>
class Data {
int val;
};
template<class T>
class Test {
public:
Test(){};
private:
typename T::container _data;
};
class FunTest:public Test<FunTest> {
public:
typedef std::map<uint16_t, FunTest > container;
FunTest():Test(){}
};
int main()
{
FunTest object;
std::cout << "Hello World!\n";
}
I tried the above but I get the error
Error C2039 'container': is not a member of 'FunTest' Temp
Any insight on why this gives an error is much appreciated.
According to user17732522
Test will instantiate the template specialization before
container is declared, so T::container cannot use it.
So I guess one solution could be to move the typedef to Test class as a protected variable.
#include <iostream>
#include <map>
template<class T>
class Test {
public:
Test() {};
protected:
typedef std::map<uint16_t, T> container;
private:
typename container _data;
};
class FunTest :public Test<FunTest> {
public:
FunTest() :Test() {}
//Test<FunTest>::container c; access here as well if needed
};
int main()
{
FunTest object;
std::cout << "Hello World!\n";
}

How to get the value of a template class?

I'm trying to get the value of a template class. To get the value of a class, I can easily do like:
int get_value()
{
return *this;
}
But I want to create a class, and extend it, and don't make get_value() in all classes again. So, I did that:
template<typename T>
class _extend : public T
{
public:
auto _get_value()
{
return *this;
}
};
template<typename T>
class extend : public _extend<T>
{
public:
T get_value()
{
auto value = this->_get_value(); /* It was `_get_value()`, changed to `this->_get_value()` due to the comments */
T output = value;
return output;
}
};
But it's not working: output is nothing.
Edit
Sample program:
#include <iostream>
namespace kc
{
template<typename T>
class _extend : public T
{
public:
auto _get_value()
{
return *this;
}
};
template<typename T>
class extend : public _extend<T>
{
public:
T get_value()
{
auto value = this->_get_value();
T output = value;
return output;
}
};
class A : public std::string, public extend<std::string>
{
public:
using std::string::string;
};
}
int main()
{
kc::A a("a");
std::cout << a.get_value() << std::endl;
}
The problem with the code in the question is the multiple inheritance. The *this that _extend<string>::get_value() will be called with is not the string that has a value.
Although I agree with #NicolBolas in comments in that I don't understand why you want this, but you can make a class template that will return the value of what it derives from with only one level of inheritance. You just need to give it a perfect forwarding constructor and have get_value() cast to the base type, i.e.
#include <iostream>
#include <string>
namespace kc
{
template<typename T>
class extend : public T
{
public:
template<typename... Args>
extend(Args&&... args) : T(std::forward<Args>(args)...)
{}
T get_value()
{
return *static_cast<T*>(this);
}
};
}
int main()
{
kc::extend<std::string> a("foo");
std::cout << a.get_value() << std::endl;
}
Basically:
template<class C>
class extend : public C
{
public:
using C::C;
auto get()
{
return *this;
}
};
And a full example:
#include <iostream>
template<class C>
class extend : public C
{
public:
using C::C;
auto get()
{
return *this;
}
};
class e_string : public extend<std::string>
{
public:
using extend<std::string>::extend;
};
int main()
{
e_string s = "Test";
std::cout << s.get() << std::endl;
}

Alternatives to exposing a template parameter from a composed class

I'm modifying a class by adding a data-member that is templated. The code will invariably be using a default template type for the template parameter in all invocations, except for one place. Partially motivated by this, and partially due to a a desire/whim, I do not want to add a template parameter to the class as shown below:
#include <iostream>
template <typename Der>
class A : private Der {
public:
int get() { return Der::get_(); }
};
class B {
protected:
int get_() { return 20; }
};
class C {
protected:
int get_() { return 30; }
};
using Default = B;
template <class T = Default>
class User {
public:
User() {}
A<T>& getMember() { return m_; }
private:
A<T> m_; // This is what I am adding, and exposing param T.
};
int main(int argc, char* argv[]) {
User h;
std::cout<<h.getMember().get()<<std::endl;
}
One solution that I could think of is the use of a sum-type, but this introduces some exception handling code:
class User {
public:
User() : m_(A<Default>()) {}
template <typename T>
User(const T& in) : m_(in) {}
template <typename T>
A<T>& getMember() { return std::get<A<T>>(m_); }
private:
std::variant<A<B>, A<C>> m_;
};
I'm looking for:
A name for what I am trying to do, if it exists.
Ways in which I can accomplish what I desire.
This is not an answer, as I don't find the virtual function call completely satisfactory, but, as progress, another option I can share is type-erasure using an inner base class.
Something like:
#include <iostream>
#include <memory>
class User {
public:
template <class T>
User(T&&) : m_(new Internal<T>()) {}
int doOnMember() { return m_->doOnMember(); }
private:
class InternalBase {
public:
virtual int doOnMember() = 0;
};
template <typename T>
class Internal : public InternalBase {
public:
Internal() {}
int doOnMember() { return m_.get(); }
private:
A<T> m_;
};
private:
std::shared_ptr<InternalBase> m_;
};
int main(int argc, char* argv[]) {
User h(B{});
std::cout<<h.doOnMember()<<std::endl;
User h1(C{});
std::cout<<h1.doOnMember()<<std::endl;
}

Using SFINAE to disable template class member function

Is it possible to use SFINAE and std::enable_if to disable a single member function of a template class?
I currently have a code similar to this:
#include <type_traits>
#include <iostream>
#include <cassert>
#include <string>
class Base {
public:
virtual int f() { return 0; }
};
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
assert((std::is_same<T, int>::value));
T val = getValue_();
//return val; --> not possible if T not convertible to int
return *reinterpret_cast<int*>(&val);
}
};
template<typename T>
class MoreDerived : public Derived<T> {
public:
int f() override { return 2; }
};
int main() {
Derived<int> i;
MoreDerived<std::string> f;
std::cout << f.f() << " " << i.f() << std::endl;
}
Ideally, Derived<T>::f() should be disabled if T != int. Because f is virtual, Derived<T>::f() gets generated for any instantiation of Derived, even if it is never called.
But the code is used such that Derived<T> (with T != int) never gets created only as a base class of MoreDerived<T>.
So the hack in Derived<T>::f() is necessary to make the program compile; the reinterpret_cast line never gets executed.
You could simply specialize f for int:
template<typename T>
class Derived : public Base {
private:
T getValue_() { return T(); }
public:
int f() override {
return Base::f();
}
};
template <>
int Derived<int>::f () {
return getValue_();
}
No you can't rule out a member function with SFINAE. You could do it with specialisation of your Derived class f member function for convertible Ts to int but that would lead to unnecessary duplication of code. In C++17 however you could solve this with use of if constexpr:
template<typename T> class Derived : public Base {
T getValue_() { return T(); }
public:
int f() override {
if constexpr(std::is_convertible<T, int>::value) return getValue_();
return Base::f();
}
};
Live Demo

How to enable_shared_from_this of both parent and derived

I have simple base and derived class that I want both have shared_from_this().
This simple solution:
class foo : public enable_shared_from_this<foo> {
void foo_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&foo::foo_do_it,shared_from_this());
}
virtual ~foo() {};
};
class bar1 : public foo , public enable_shared_from_this<bar1> {
using enable_shared_from_this<bar1>::shared_from_this;
void bar1_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&bar1::bar1_do_it,shared_from_this());
}
};
Causes exception tr1::bad_weak_ptr in following code:
shared_ptr<foo> ptr(shared_ptr<foo>(new bar1));
function<void()> f=ptr->get_callback();
f();
So after "googling" I have found following solution:
class bar2 : public foo {
void bar2_do_it()
{
cout<<"foo::do_it\n";
}
shared_ptr<bar2> shared_from_this()
{
return boost::static_pointer_cast<bar2>(foo::shared_from_this());
}
public:
virtual function<void()> get_callback()
{
return boost::bind(&bar2::bar2_do_it,shared_from_this());
}
};
And now it works.
Is there any better and more convinient and correct way to enable_shared_from_this for both parent and child?
Thanks
The OP solution can be made more convenient by defining the following on the base class.
protected:
template <typename Derived>
std::shared_ptr<Derived> shared_from_base()
{
return std::static_pointer_cast<Derived>(shared_from_this());
}
This can be made more convenient by placing it in a base class (for reuse).
#include <memory>
template <class Base>
class enable_shared_from_base
: public std::enable_shared_from_this<Base>
{
protected:
template <class Derived>
std::shared_ptr<Derived> shared_from_base()
{
return std::static_pointer_cast<Derived>(shared_from_this());
}
};
and then deriving from it as follows.
#include <functional>
#include <iostream>
class foo : public enable_shared_from_base<foo> {
void foo_do_it()
{
std::cout << "foo::do_it\n";
}
public:
virtual std::function<void()> get_callback()
{
return std::bind(&foo::foo_do_it, shared_from_base<foo>());
}
};
class bar1 : public foo {
void bar1_do_it()
{
std::cout << "bar1::do_it\n";
}
public:
virtual std::function<void()> get_callback() override
{
return std::bind(&bar1::bar1_do_it, shared_from_base<bar1>());
}
};
Sorry, but there isn't.
The problem is that shared_ptr<foo> and shared_ptr<bar1> are different types. I don't understand everything that's going on under the hood, but I think that when the constructor returns and is assigned to a shared_ptr<foo>, the internal weak_ptr<bar1> sees that nothing is pointing to it (because only a shared_ptr<bar1> would increment the counter) and resets itself. When you call bar1::shared_from_this in get_callback, you get the exception because the internal weak_ptr isn't pointing to anything.
Essentially, enable_shared_from_this only seems to work transparently from a single class in a hierarchy. If you try implementing it manually, the problem should become obvious.
A similar solution to #evoskuil that reduces boilerplate in derived classes should you want to implement a shared_from_this() function, resulting in the following code at the point of use in the class:
auto shared_from_this() {
return shared_from(this);
}
This uses 'shim' functions outside of the class. By doing it that way it also provides a clean way to do this for classes who's interface can't be modified but derive from enable_shared_from_this - e.g.
auto shared_that = shared_from(that);
Note: Use of auto for return types here will depend upon the age of your compiler.
Shim functions that could be placed in a library header:
template <typename Base>
inline std::shared_ptr<Base>
shared_from_base(std::enable_shared_from_this<Base>* base)
{
return base->shared_from_this();
}
template <typename Base>
inline std::shared_ptr<const Base>
shared_from_base(std::enable_shared_from_this<Base> const* base)
{
return base->shared_from_this();
}
template <typename That>
inline std::shared_ptr<That>
shared_from(That* that)
{
return std::static_pointer_cast<That>(shared_from_base(that));
}
The above code relies on the fact that the type passed to shared_from(...) inherits from std::enable_shared_from_this<Base> at some point in its ancestry.
Calling shared_from_base will figure out what type that ultimately was. Since we know that That inherits from Base, a static downcast can be made.
Probably there are some pathological corner cases with classes having type conversion operators.. but that's unlikely to occur in code not designed to break this.
Example:
struct base : public std::enable_shared_from_this<base> {};
struct derived : public base
{
auto shared_from_this() {
return shared_from(this);
}
// Can also provide a version for const:
auto shared_from_this() const {
return shared_from(this);
}
// Note that it is also possible to use shared_from(...) from
// outside the class, e.g.
// auto sp = shared_from(that);
};
template <typename X>
struct derived_x : public derived
{
auto shared_from_this() {
return shared_from(this);
}
};
Compilation test:
int main()
{
auto pbase = std::make_shared<base>();
auto pderived = std::make_shared<derived>();
auto pderived_x = std::make_shared<derived_x<int> >();
auto const& const_pderived = *pderived;
const_pderived.shared_from_this();
std::shared_ptr<base> test1 = pbase->shared_from_this();
std::shared_ptr<derived> test2 = pderived->shared_from_this();
std::shared_ptr<derived_x<int> > test3 = pderived_x->shared_from_this();
return 0;
}
https://onlinegdb.com/SJWM5CYIG
Prior solution that I posted, kept to make the comments still make sense - this placed the functions in the base class which had some problems - particularly non-uniformity between the required implementation for 'normal' classes and template classes.
Additionally the implementation in the base class would need to be repeated for new class hierarchies which is not all that DRY.
Furthermore the base class function suffered from the possibility of misuse by supplying a base class pointer from a different object. The newer scheme above avoids this entirely and the runtime assert(...) check goes.
Old implementation:
#include <cassert>
#include <memory>
class base : public std::enable_shared_from_this<base>
{
protected:
template <typename T>
std::shared_ptr<T> shared_from(T* derived) {
assert(this == derived);
return std::static_pointer_cast<T>(shared_from_this());
}
};
class derived : public base
{
public:
auto shared_from_this() {
return shared_from(this);
}
};
template <typename X>
class derived_x : public derived
{
public:
auto shared_from_this() {
return this->template shared_from(this);
}
};
int main()
{
auto pbase = std::make_shared<base>();
auto pderived = std::make_shared<derived>();
auto pderived_x = std::make_shared<derived_x<int> >();
std::shared_ptr<base> test1 = pbase->shared_from_this();
std::shared_ptr<derived> test2 = pderived->shared_from_this();
std::shared_ptr<derived_x<int> > test3 = pderived_x->shared_from_this();
return 0;
}
Quite easy; inherit public shared_from_this only in your base class. Implement an accessor in your derived class that casts to the appropriate type;
std::shared_ptr<Derived> shared()
{
return std::dynamic_pointer_cast<Derived>(Base::shared_from_this());
}
With c++23 deducing this, things become much easier. https://godbolt.org/z/j499WK58Y
#include <memory>
#include <iostream>
#include <functional>
using namespace std;
struct new_enable_shared_from_this :
public std::enable_shared_from_this<new_enable_shared_from_this> {
template <typename Self>
auto new_shared_from_this(this Self& self) {
return std::static_pointer_cast<Self>(self.shared_from_this());
}
};
class foo : public new_enable_shared_from_this {
void foo_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return bind(&foo::foo_do_it,new_shared_from_this());
}
virtual ~foo() {};
};
class bar1 : public foo {
void bar1_do_it()
{
cout<<"foo::do_it\n";
}
public:
virtual function<void()> get_callback()
{
return bind(&bar1::bar1_do_it,new_shared_from_this());
}
};
int main() {
auto pf = std::make_shared<foo>();
pf->get_callback()();
auto pb = std::make_shared<bar1>();
pb->get_callback()();
}
This is the previous answer:
Well, I don't like virtual function. Virtual function is just for type erasing, but we don't need type erasing all the time. So, provide a mechanism for type erasing is enough. Here is an example that don't use virtual function:
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
template<typename derived>
class foo_imp {
void foo_do_it()
{
cout<<"foo::do_it\n";
}
public:
function<void()> get_callback()
{
auto&& d = static_cast<derived&>(*this);
return bind(&foo_imp::foo_do_it, d.shared_from_this());
}
};
template<typename derived>
class bar_imp {
void bar_do_it()
{
cout<<"bar::do_it\n";
}
public:
function<void()> get_callback()
{
auto&& d = static_cast<derived&>(*this);
return bind(&bar_imp::bar_do_it, d.shared_from_this());
}
};
struct foo : public foo_imp<foo>, public enable_shared_from_this<foo> {};
struct bar : public bar_imp<bar>, public enable_shared_from_this<bar> {};
struct v_foo {
virtual function<void()> get_callback() = 0;
};
template <typename T>
std::shared_ptr<v_foo> convert(const std::shared_ptr<T>& st) {
struct _ : public v_foo {
_(const std::shared_ptr<T>& st) : _st{st} {}
function<void()> get_callback() override {
return _st->get_callback();
}
std::shared_ptr<T> _st;
};
return std::make_shared<_>(st);
}
int main() {
auto sf = make_shared<bar>();
sf->get_callback()();
auto svf = convert(sf);
svf->get_callback()();
auto sb = make_shared<foo>();
sb->get_callback()();
auto svb = convert(sb);
svb->get_callback()();
}
#include <memory>
template<class T>
class Base : public std::enable_shared_from_this<T> {
};
class Derived : public Base<Derived> {
std::shared_ptr<Derived> getDerived() { return shared_from_this(); }
};