How to get the value of a template class? - c++

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;
}

Related

Can I get the current class type id from a static base method?

Is there anyway to get a type from a static base class method? For instance
class A
{
static std::type_info getClassType
{
// What do I do here
}
};
class B : public A
{
};
B instance;
auto my_type = instance::getClassType()
With C++'s lack of static variable overloading, I am having a hard time figuring out a way to determine class type across classes without doing a special virtual function in every child class which I am trying to avoid due to the sheer number.
Make a class that will be a template.
Subclass from it. Pass the child type as the template parameter.
With that, base class will know the child. The T will be the child type.
Code:
#include <iostream>
using namespace std;
template<typename T> class thebase
{
static T instance;
public:
static T& getInstance() { return instance; }
};
template <typename T> T thebase<T>::instance;
class sub1 : public thebase<sub1> {
public: void tell() { std::cout << "hello1: " << this << std::endl; }
};
class sub2 : public thebase<sub2> {
public: void tell() { std::cout << "hello2: " << this << std::endl; }
};
int main() {
sub1& ref1 = sub1::getInstance();
sub1& ref2 = sub1::getInstance();
std::cout << ((&ref1) == (&ref2)) << std::endl;
sub1::getInstance().tell();
sub2::getInstance().tell();
sub1::getInstance().tell();
sub2::getInstance().tell();
return 0;
}
Output:
1
hello1: 0x55874bff1193
hello2: 0x55874bff1192
hello1: 0x55874bff1193
hello2: 0x55874bff1192
This kind of code pattern is sometimes called CRTP
it boils down to there being a manager class that keeps track of one instance of a variety of classes and their states. You may use this singleton "instance" of these sub classes, but I want to be able to say MySubClass::instance() and then have it get the correct instance from the manager without having to write it in each sub class.
You can implement the managed classes using CRTP ("Curiously recurring template pattern") so a base class knows the derived class types and can then delegate that information to the manager class.
Try something like this:
#include <map>
#include <typeinfo>
#include <typeindex>
class Base {
public:
virtual ~Base() {}
};
class Manager
{
private:
static std::map<std::type_index, Base*> m_instances;
public:
template<typename T>
static void addInstance(Base *inst) {
if (!m_instances.insert(std::make_pair(std::type_index(typeid(T)), inst)).second)
throw ...; // only 1 instance allowed at a time!
}
template<typename T>
static void removeInstance() {
auto iter = m_instances.find(std::type_index(typeid(T)));
if (iter != m_instances.end())
m_instances.erase(iter);
}
template<typename T>
static T* getInstance() {
auto iter = m_instances.find(std::type_index(typeid(T)));
if (iter != m_instances.end())
return static_cast<T*>(iter->second);
return nullptr;
}
};
std::map<std::type_index, Base*> Manager::m_instances;
template<class Derived>
class A : public Base
{
public:
A() {
Manager::addInstance<Derived>(this);
}
~A() {
Manager::removeInstance<Derived>();
}
static Derived* getInstance() {
return Manager::getInstance<Derived>();
}
};
class B : public A<B>
{
...
};
class C : public A<C>
{
...
};
B b_inst;
C c_inst;
...
B *pB = B::getInstance();
if (pB) ...
C *pC = C::getInstance();
if (pC) ...
Live Demo
Based on your own example of code in your own answer, here's a final result working:
# include <iostream>
# include <typeinfo>
template <class T>
class A
{
public:
static const std::type_info& getClassType()
{
return typeid(T);
}
};
class B : public A<B>
{ /* ... */ };
class C : public A<C>
{ /* ... */};
class D : public A<D>
{ /* ... */};
int main()
{
B b; C c; D d;
auto& b_type = b.getClassType();
auto& c_type = c.getClassType();
auto& d_type = d.getClassType();
std::cout << b_type.name() << std::endl;
std::cout << c_type.name() << std::endl;
std::cout << d_type.name() << std::endl;
}
Output:
1B 1C 1D
Someone above mentioned the CRTP or "Curiously recurring template pattern". Using this, I have not tested it, but it appears I may be able to write:
template <class T>
class A
{
static std::type_info getClassType
{
return typeid(T);
}
};
class B : public A<B>
{
};
B instance;
auto my_type = instance::getClassType()

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

Enforcing calling a method in all base classes

How can one implement a method which calls another method recursively for all base classes? Conceptually:
class C {
public:
magical void recursiveWork() {
thisClass::doWork();
if (baseClassExists) {
baseClass::recursiveWork();
}
}
void doWork() {
printf("bar");
}
}
class D : public C {
public:
void doWork() {
printf("foo");
}
}
D d;
d.recursiveWork(); // prints "foobar"
You could use something to indicate the base class, like base_type below, and then recursively check if DoIt exists. (in this case I checked if base_type is different from self, in case of the most base class). Of course, it won't work with multiple inheritance (it should have something to identify all base_type's), and be careful with object slicing when going up on base classes.
#include <iostream>
#include <utility>
class A1
{
public:
using base_type = A1;
virtual ~A1(){}
virtual void DoIt(){ std::cout << "A1\n"; }
};
class A : public A1
{
public:
using base_type = A1;
virtual void DoIt(){
std::cout << "A\n";
}
};
class B : public A
{
public:
using base_type = A;
virtual void DoIt(){
std::cout << "B\n";
}
};
template<class...> using void_t = void;
template<class, class = void>
struct has_do_it : std::false_type { constexpr static bool value = false; };
template<class T>
struct has_do_it<T, void_t<decltype(std::declval<T&>().DoIt())>> : std::true_type { constexpr static bool value = true; };
template<typename T>
void DoItRec(T t)
{
if (has_do_it<T>::value) {
t.DoIt();
if(!std::is_same<T, typename T::base_type>::value)
{
typename T::base_type& base = t; // get base part (object slicing)
DoItRec(base);
}
}
}
int main()
{
B b;
DoItRec(b);
return 0;
}
Live example

Is there another simple way to do with c++ properties?

I've tried to use c++ properties and now I'm stuck with this:
class a {
protected:
// wikipedia https://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
template<class s, typename t>
class getonly {
protected:
friend s;
t value;
t set(); // operator =...
public:
t get(); // t operator...
};
};
class b : public a {
public:
getonly<b, int> id;
};
What I want is something like this, where getonly is parametrized by only the typename (int), and not the class (b):
class b : public a {
public:
getonly<int> id;
};
Is this possible? Can anyone help me?
It appears that you want a data member that can be read by any code, but that can only be changed by the containing class.
The attempt at providing friend-ship via template would not have compiled prior to C++11. It means that this code can not be easily modified to work with a C++03 compiler (with C++03 one could express the access restriction on modification via e.g. an owner credential argument to a setter). However, that concern becomes less significant every day.
Here's your code modified to compile, and with the inheritance changed from public to private (it doesn't make much sense to say that b "is-an" a):
class a {
protected:
// wikipedia https://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
template<class s, typename t>
class getonly {
protected:
friend s;
t value_;
public:
auto get() const -> t const& { return value_; }
operator t const& () const { return value_; }
getonly( t v ): value_( v ) {}
};
};
class b : private a {
public:
getonly<b, int> id;
void set_id( int x ) { id.value_ = 2*x; }
b(): id( 42 ) {}
};
#include <iostream>
auto main() -> int
{
using namespace std;
b obj;
cout << obj.id << endl;
obj.set_id( 333 );
cout << obj.id << endl;
}
So first off, this can be done with CRTP
template<typename s>
class a {
protected:
// wikipedia https://en.wikipedia.org/wiki/Property_(programming)#C.2B.2B
template<typename t>
class getonly {
protected:
friend s;
t value;
t set(); // operator =...
public:
t get(); // t operator...
};
};
class b : public a<b> {
public:
getonly<int> id;
};
But since you mentioned inheritance, are you aware that friend declarations are not inherited? If that is your goal, then there is a more elegant solution - do not use the property as a base class but as traits:
template<typename T, typename F>
class property_impl
{
friend F;
private:
T value_;
protected:
void set(T value)
{
value_ = value;
}
public:
T get()
{
return value_;
}
};
template<typename F>
class property_traits
{
template<typename T> using property = property_impl < T, F > ;
};
class foo : public property_traits < foo >
{
public:
property<int> id_;
};
class bar : public foo, public property_traits < bar >
{
public:
property<int> another_id_;
void doStuff(foo f)
{
auto value = f.id_.get();
// f.id_.set(5); <-- fails since friend is not inherited
}
};
int main(int argc, char** argv)
{
foo f;
auto value = f.id_.get();
bar b;
auto another_value = b.another_id_.get();
b.doStuff(f);
return 0;
}
This will give you the ability to inherit and specialize on each class that needs a property while retianing the fact, that only the class type used in specialization is able to modify the value.
Again, maybe you want that, I am not sure.

c++ polymorphism : return type of a virtual method

My main class is :
class Data{
public:
Data(std::string name):name_(name){};
virtual ~Data(){};
protected:
std::string name_;
};
Since I'd like to allow any kind of data, I use a template to create my inherited class :
template<typename Type>
class GenericData : public Data{
public:
GenericData(std::string name, Type t);
private:
Type t_;
};
template<typename Type>
GenericData<Type>::GenericData(std::string name, Type t):
Data(name),
t_(t)
{}
The third class is a collection of (Generic)Data :
class Input{
public:
Input();
~Input();
private:
std::vector<Data*> d_;
};
Input::Input(){
d_.push_back(new GenericData("double",3.2);
d_.push_back(new GenericData("int",2);
}
Input::~Input(){
for(unsigned int i(0);i<d_.size();i++){
delete d_[i];
d_[i] = NULL;
}
}
The thing that I don't know how to do is to get the t_ value from from the Input class. I'd like to have a templata<typename Type> Type Input::get(unsigned int i) method that returns t_. I guess that I should create a virtual method in Data and another method in GenericData but I can't make it work.
It's pretty straightforward:
#include <string>
#include <vector>
#include <iostream>
class Data{
public:
Data(std::string name):name_(name){};
virtual ~Data(){};
protected:
std::string name_;
};
template<typename Type>
class GenericData : public Data{
public:
GenericData(std::string name, Type t);
Type Get() { return t_; }
private:
Type t_;
};
template<typename Type>
GenericData<Type>::GenericData(std::string name, Type t):
Data(name),
t_(t)
{}
class Input{
public:
Input() {}
~Input();
void Add(Data*v) {d_.push_back(v);}
template<typename T>
T Get(int i) {
return dynamic_cast< GenericData<T> *>(d_[i])->Get();
}
private:
std::vector<Data*> d_;
};
Input::~Input(){
for(unsigned int i(0);i<d_.size();i++){
delete d_[i];
d_[i] = NULL;
}
}
int main() {
Input inp;
inp.Add(new GenericData<int>("1", 1));
inp.Add(new GenericData<double>("2", 2.0));
std::cout << "1: " << inp.Get<int>(0) << "; 2: " << inp.Get<double>(1) << std::endl;
return 0;
}
That's quite problematic. First of all, you have to provide some way to get it from Data, for example:
(inside GenericData)
public:
T GetValue()
{
// Consider naming t_ more informative
return t_;
}
Secondly, you can create a generic method for getting data in Input:
(inside Input)
public:
template <typename T>
GenericData<T> * GetData(int index)
{
return dynamic_cast<GenericData<T> *>(_d[index]);
}
or, simpler:
(inside Input)
public:
template <typename T>
T GetValue(int index)
{
return (dynamic_cast<GenericData<T> *>(_d[index]))->GetValue();
}