Is it possible to inherit a specialized struct/class like following?
template<class TKey, class TData>
struct Container
{
virtual void Add(TKey key, TData data) = 0;
};
template<class TData>
struct Container<int, TData>
{
virtual void Add(int key, TData data) = 0;
};
struct TicketContainer : public Container<std::string>
{
void Add(int key, std::string data)
{
}
};
I am getting errors in TicketContainer declaration complaining too few template parameters declared.
Change:
struct TicketContainer : public Container<std::string>
to:
struct TicketContainer : public Container<int, std::string>
or some other type for TKey.
Even though you have provided a partial specialization of Container you still need to specify both of the template parameters.
You can specify default types for template parameters if you do not want to specify both template parameters. In this case, you would have to reorder TKey and TValue (which may be counter intuitive as associative containers are normally declared key then value):
// Reordered 'TData' and 'TKey'.
template<class TData, class TKey = int>
struct Container
{
virtual void Add(TKey key, TData data) = 0;
};
template<class TData>
struct Container<TData> // Equivalent to 'struct Container<TData, int>'
{
// This specialization seems pointless as it defines no
// special behaviour.
virtual void Add(int key, TData data) = 0;
};
struct TicketContainer : public Container<std::string>
{
};
Related
I am lazy I don't want to write the same code twice, so how can I avoid it in this case?
I have nodes in a tree some of them has a member _key like this:
struct node_base {
virtual void foo()=0;
virtual ~node_base() {}
}
template<typename Key>
struct node_key: public node_base {
node_key(Key k): _key(k) {}
virtual ~node_key() {}
protected:
Key _key;
};
Now I have two types of child nodes one which inherits from node_key and one which only inherits from node_base
struct no_key {};
template<typename Key, typename Data>
struct child: public node_key<Key> {
…
void foo() {
//do something with _data
}
protected:
Data _data;
}
template<typename Data>
struct child<no_key,Data>: public node_base {
…
void foo() {
//do something with _data
}
protected:
Data _data;
}
However at you see I write foo twice and it is identical in both cases. Can I do something to ensure reuse?
The advantage of node_key is that I can have a pointer
node_key<int> *p=new child<int,int>
…
p->foo();
and it will fail at compile time if p=new child< int > which is fine. I can also have a pointer.
node_base *p=get_a_child();
p->foo();
More about my tree here:
https://www.facebook.com/profile.php?id=100013861179843
You can chose the base class of child using a traits struct:
struct no_key {};
template<typename Key, typename Data>
struct child_base_traits {
typedef node_key<Key> type;
};
template<typename Data>
struct child_base_traits<no_key, Data> {
typedef node_base type;
};
template<typename Key, typename Data>
struct child: public typename child_base_traits<Key,Data>::type {
void foo() {
//do something with _data
}
protected:
Data _data;
};
Or, as #Igor suggested, just specialize node_key<no_key>:
template<>
struct node_key<no_key> : node_base {} ;
To implement a property system for polymorphic objects, I first declared the following structure:
enum class access_rights_t
{
NONE = 0,
READ = 1 << 0,
WRITE = 1 << 1,
READ_WRITE = READ | WRITE
};
struct property_format
{
type_index type;
string name;
access_rights_t access_rights;
};
So a property is defined with a type, a name and access rights (read-only, write-only or read-write). Then I started the property class as follows:
template<typename Base>
class property : property_format
{
public:
template<typename Derived, typename T>
using get_t = function<T(const Derived&)>;
template<typename Derived, typename T>
using set_t = function<void(Derived&, const T&)>;
private:
get_t<Base, any> get_f;
set_t<Base, any> set_f;
The property is associated to a base type, but may (and will) be filled with accessors associated to an instance of a derived type. The accessors will be encapsulated with functions accessing std::any objects on an instance of type Base. The get and set methods are declared as follows (type checking are not shown here to make the code minimal):
public:
template<typename T>
T get(const Base& b) const
{
return any_cast<T>(this->get_f(b));
}
template<typename T>
void set(Base& b, const T& value_)
{
this->set_f(b, any(value_));
}
Then the constructors (access rights are set to NONE to make the code minimal):
template<typename Derived, typename T>
property(
const string& name_,
get_t<Derived, T> get_,
set_t<Derived, T> set_ = nullptr
):
property_format{
typeid(T),
name_,
access_rights_t::NONE
},
get_f{caller<Derived, T>{get_}},
set_f{caller<Derived, T>{set_}}
{
}
template<typename Derived, typename T>
property(
const string& name_,
set_t<Derived, T> set_
):
property{
name_,
nullptr,
set_
}
{
}
The functions passed as arguments are encapsulated through the helper structure caller:
private:
template<typename Derived, typename T>
struct caller
{
get_t<Derived, T> get_f;
set_t<Derived, T> set_f;
caller(get_t<Derived, T> get_):
get_f{get_}
{
}
caller(set_t<Derived, T> set_):
set_f{set_}
{
}
any operator()(const Base& object_)
{
return any{
this->get_f(
static_cast<const Derived&>(object_)
)
};
}
void operator()(Base& object_, const any& value_)
{
this->set_f(
static_cast<Derived&>(object_),
any_cast<Value>(value_)
);
}
};
Now, considering these dummy classes.
struct foo
{
};
struct bar : foo
{
int i, j;
bar(int i_, int j_):
i{i_},
j{j_}
{
}
int get_i() const {return i;}
void set_i(const int& i_) { this->i = i_; }
};
I can write the following code:
int main()
{
// declare accessors through bar methods
property<foo>::get_t<bar, int> get_i = &bar::get_i;
property<foo>::set_t<bar, int> set_i = &bar::set_i;
// declare a read-write property
property<foo> p_i{"bar_i", get_i, set_i};
// declare a getter through a lambda
property<foo>::get_t<bar, int> get_j = [](const bar& b_){ return b_.j; };
// declare a read-only property
property<foo> p_j{"bar_j", get_j};
// dummy usage
bar b{42, 24};
foo& f = b;
cout << p_i.get<int>(f) << " " << p_j.get<int>(f) << endl;
p_i.set<int>(f, 43);
cout << p_i.get<int>(f) << endl;
}
My problem is that template type deduction doesn't allow me to declare a property directly passing the accessors as arguments, as in:
property<foo> p_i{"bar_i", &bar::get_i, &bar::set_i};
Which produces the following error:
prog.cc:62:5: note: template argument deduction/substitution failed:
prog.cc:149:50: note: mismatched types std::function<void(Type&, const Value&)> and int (bar::*)() const
property<foo> p_i{"bar_i", &bar::get_i, set_i};
Is there a way to address this problem while keeping the code "simple"?
A complete live example is available here.
std::function is a type erasure type. Type erasure types are not suitable for deduction.
template<typename Derived, typename T>
using get_t = function<T(const Derived&)>;
get_t is an alias to a type erasure type. Ditto.
Create traits classes:
template<class T>
struct gettor_traits : std::false_type {};
this will tell you if T is a valid gettor, and if so what its input and output types are. Similarly for settor_traits.
So
template<class T, class Derived>
struct gettor_traits< std::function<T(Derived const&)> >:
std::true_type
{
using return_type = T;
using argument_type = Derived;
};
template<class T, class Derived>
struct gettor_traits< T(Derived::*)() >:
std::true_type
{
using return_type = T;
using argument_type = Derived;
};
etc.
Now we got back to the property ctor:
template<class Gettor,
std::enable_if_t< gettor_traits<Gettor>{}, int> =0,
class T = typename gettor_traits<Gettor>::return_value,
class Derived = typename gettor_traits<Gettor>::argument_type
>
property(
const string& name_,
Gettor get_
):
property_format{
typeid(T),
name_,
access_rights_t::NONE
},
get_f{caller<Derived, T>{get_}},
nullptr
{
}
where we use SFINAE to ensure that our Gettor passes muster, and the traits class to extract the types we care about.
There is going to be lots of work here. But it is write-once work.
My preferred syntax in these cases would be:
std::cout << (f->*p_i)();
and
(f->*p_i)(7);
where the property acts like a member function pointer, or even
(f->*p_i) = 7;
std::cout << (f->*p_i);
where the property transparently acts like a member variable pointer.
In both cases, through overload of ->*, and in the second case via returning a pseudo-reference from ->*.
At the end of this answer is a slightly different approach. I will begin with the general problem though.
The problem is &bar::get_i is a function pointer to a member function while your alias is creating a function object which needs the class as additional template parameter.
Some examples:
Non member function:
#include <functional>
void a(int i) {};
void f(std::function<void(int)> func)
{
}
int main()
{
f(&a);
return 0;
}
This works fine. Now if I change a into a struct:
#include <functional>
struct A
{
void a(int i) {};
};
void f(std::function<void(int)> func)
{
}
int main()
{
f(std::function<void(int)>(&A::a));
return 0;
}
this gets the error:
error: no matching function for call to std::function<void(int)>::function(void (A::*)(int))'
because the std::function object also need the base class (as you do with your alias declaration)
You need a std::function<void(A,int)>
You cannot make your example much better though.
A way to make it a "bit" more easier than your example would maybe be this approach using CRTP.
#include <functional>
template <typename Class>
struct funcPtr
{
template <typename type>
using fun = std::function<void(Class,type)>;
};
struct A : public funcPtr<A>
{
void a(int i) {};
};
void f(A::fun<int> func)
{
};
int main()
{
f(A::fun<int>(&A::a));
return 0;
}
And each your "derived" classes derives from a funcPtr class which "auto generates" the specific alias declaration.
I'm currently playing around with templates in C++ and got stuck with template template parameters.
Lets say I have the following classes:
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template< template<typename T> typename ImplType>
class MyHub
{
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
In essence I would like to have a static class like MyHub that accepts an implementation of MyInterface and provides certain static methods to use them like static T Foo().
Then I tried to use MyHub:
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
Unfortunately I always end up getting an error saying that the type T (of static T Foo() in MyHub) does not name a type.
I would expect that it works because
the template parameter of the template parameter Impl is named T
MyHub is a templated class with one template parameter and contains a method Foo
So far I couldn't find a solution for this after digging through documentations and google results so I hope some of you can help me.
You can use typedefs. Also, since your implementation classes are not template class, there is no need for template template parameters.
#include <iostream>
#include <string>
template<typename T>
struct MyInterface
{
virtual T Foo() = 0;
typedef T Type;
};
class MyIntImpl : public MyInterface<int>
{
public:
int Foo() { return 2; }
};
class MyStringImpl : public MyInterface<std::string>
{
public:
std::string Foo() { return "haha"; }
};
template<class ImplType>
class MyHub
{
public:
static typename ImplType::Type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
std::cout << MyHub<MyIntImpl>::Foo() << "\n"; // prints 2
std::cout << MyHub<MyStringImpl>::Foo() << "\n"; // print haha
return 0;
}
Here is an example.
MyImpl is not a class template; so can't be passed as the template parameter of MyInterface.
You could change your MyInterface, MyImpl and MyHub classes to:
template<typename T>
class MyInterface{
public:
virtual T foo() = 0;
};
class MyImpl: public MyInterface<int>{
public:
using value_type = int;
value_type foo(){ return 1; /* dummy */ }
};
template<typename Impl, typename = std::enable_if_t<std::is_base_of<Impl, MyInterface<typename Impl::value_type>>::value>>
class MyHub{
public:
static auto foo(){
static Impl i;
return i.foo();
}
};
Which lets you use it the same way you are in your example.
The std::is_base_of check might be a little unnecessary in this case; but, this way you can't accidentally pass in another class that isn't derived from MyInterface with a method foo().
The STL uses value_type as a place holder for the underlying type of a template class. You could possibly do the same for your solution.
template<typename T>
struct MyInterface
{
typedef T value_type;
virtual T Foo() = 0;
}
class MyImpl : public MyInterface<int>
{
public:
int Foo() { /*...*/ }
};
template<typename ImplType>
class MyHub
{
public:
static typename ImplType::value_type Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
Also note that in c++14, typename ImplType::value_type can be replaced by auto:
static auto Foo()
{
ImplType i;
return i.Foo();
}
The names of template parameters of template template parameters are effectively a purely documentational construct—they don't get included in the containing template's scope.
There's good reason for that: there is nothing to whcih they could refer in the containing template. When you have a template template parameter, you must pass a template as the argument to it, and not an instantiation of a template. In other words, you're passing a template without arguments as the argument.
This means your code is simply wrong—you're using MyImpl as an argument for MyHub, but MyImpl is a class. MyHub expects a template, not a class. The correct instantiation of MyHub would be MyHub<MyInterface>. Not that there are no template arguments after this use of MyInterface; we are passing in the template itself, not an instantiation of it.
Template template parameters are used rather rarely in practice. You only use them if you want to instantiate the parameter template with your own types. So I would expect your MyHub code to do something like this:
template <template <class> class ImplTemplate>
struct MyHub
{
typedef ImplTemplate<SomeMyHub_SpecificType> TheType;
// ... use TheType
};
This doesn't seem to be what you want to do. I believe you want a normal type template parameter, and provide a nested typedef for its T. Like this:
template <class T>
struct MyInterface
{
typedef T ParamType; // Added
virtual T Foo() = 0;
};
template<class ImplType>
class MyHub
{
typedef typename ImplType::ParamType T;
public:
static T Foo()
{
ImplType i;
return i.Foo();
}
private:
MyHub() { }
~MyHub() { }
};
int main()
{
int i = MyHub<MyImpl>::Foo();
return 0;
}
I have a template class Field<T> which inherits from a non-template abstract base class AbstractField to be able to store all different kinds of Field<T> * types in a std::vector<AbstractField *>. My setup is as follows:
#include <vector>
class AbstractField
{
public:
virtual ~AbstractField() {};
// Something similar to: template<class T> T getValue() const; ?
};
template<class T>
class Field : public AbstractField
{
private:
T d_;
public:
Field(T d) : d_(d) {}
T getValue() const { return d_; }
};
int main()
{
AbstractField *f = new Field<double>(0.1);
// How to call: f->getValue(); ?
return 0;
}
I was wondering what would be the most natural way to call f->getValue() since I can't use a virtual template member function in the AbstractField class. As far as possible, I would prefer not using boost. Any hints are welcome!
EDIT:
Corrected std::vector<Field<T> > to std::vector<AbstractField *>. Sorry for the confusion.
Maybe this:
template <typename> struct Field;
struct AbstractField
{
virtual ~AbstractField() {}
template <typename T> T getValue()
{
return dynamic_cast<Field<T>&>(*this)->get();
}
};
template <typename T> struct Field : AbstractField
{
T & get();
// ...
};
I'm still trying to get the swing of metaprogramming, and I'm stumped.
What's I'd like to do is create a class/struct/whatever, supply it a std::tuple and have it automatically generate member functions based on the object types in the tuple. The goal is to have classes derive from MessageHandler
e.g.
typedef std::tuple< MessageA, MessageB, MessageC > MessageSet;
template< class T >
class MessageHandler
{
// some magic metaprogramming would "create"...
virtual void processMsg( const MessageA& ) = 0;
virtual void processMsg( const MessageB& ) = 0;
virtual void processMsg( const MessageC& ) = 0;
};
I've read that you can't have virtual functions in templates, but I didn't know if that was still true for C++11.
Thanks.
The answer is variadic template, partial specialization, and inheritance as:
//primary template!
template<typename T>
class MessageHandler;
//variadic template, partial specialization and inheritance!
template<typename H, typename ...T>
class MessageHandler<std::tuple<H,T...>> : public MessageHandler<std::tuple<T...>>
{
virtual void processMsg( const H& ) = 0;
};
template<typename T>
class MessageHandler<std::tuple<T>>
{
virtual void processMsg( const T& ) = 0;
};
You don't need tuple to do that:
struct MessageA{};struct MessageB{};struct MessageC{};
template <typename T>
struct message_interface {
virtual void processMessage(const T& t) = 0;
};
template< typename... Args >
struct message_handler : public message_interface<Args>...
{};
struct message_impl : message_handler<MessageA, MessageB, MessageC>
{
void processMessage(const MessageA&){}
void processMessage(const MessageB&){}
void processMessage(const MessageC&){}
};
int main()
{
message_impl i;
return 0;
}
It would probably be a good idea to check if the argument list is unique and static assert on that. Also make sure it does not contain reference types or other undesirables. Those will usually end up as errors when you try to form the argument type but it will safe your users some trouble.
EDIT: If you absolutely require to support tuple add a specialization:
template< typename... Args >
struct message_handler< std::tuple<Args...> > : public message_interface<Args>...
{};