How to circumvent virtual template member functions? - c++

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();
// ...
};

Related

Variadic templates: One method per template argument

Is there a way to automatically create one method per variadic template argument?
For example, in the code below, I want to be forced to override void x(a &v) and void x(b &v) in class i:
#include <type_traits>
#include <stdlib.h>
#include <stdio.h>
class a {
};
class b {
};
template <typename ...T>
class t {
public:
virtual void x(T &v) = 0;
};
class i : public t<a, b>
{
};
int
main (int argc, char *argv[])
{
i ii;
return 0;
}
You can make a t_impl that holds the virtual function for a single T like
template <typename T>
class t_impl
{
public:
virtual void x(T &v) = 0;
};
and then t would inherit from it like
template <typename ...T>
class t : t_impl<T>... // can use public, protected or private inheritance
{
public:
using t_impl<T>::x...; // used to import t_impl<T>::x into the public space
// any additional common members
};
Instead of making t a variadic template, just template it on a single type:
template <typename T>
class t {
public:
virtual void x(T &v) = 0;
};
and inherit base classes like this instead:
class i : public t<a>, t<b>
{
virtual void x(a &v) {}
virtual void x(b &v) {}
};
Here's a demo.

Use template parameter of template template parameter

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

Virtual template function visitor workaround with template derived classes

The problem is that template <typename T> virtual void foo() is illegal, and I'm trying to use the visitor pattern to workaround that (which is known to work in general). However the derived classes of Base are template classes, and now I'm running into the virtual template problem within the visitor classes. How to work around this?
struct Base {
// template <typename T> virtual void foo() = 0; // illegal
virtual void foo (class Visitor& visitor) = 0; // The attempted solution
};
template <typename D>
struct Derived : Base {
virtual void foo (Visitor&) override;
};
struct Visitor {
//template <typename D> // same problem again!
virtual void visit (Derived<D>*) const = 0;
};
template <typename T, typename D>
struct FooVisitor : Visitor {
virtual void visit (Derived<D>*) const override {/*Do whatever with T*/}
};
template <typename D>
void Derived<D>::foo (Visitor& visitor) {visitor.visit(this);}
With all solutions, let's assume there shall be about one hundred values for D, with new D classes being introduced constantly. And each will use D in the same way. For simplicity, let's assume each visit function will use D with
func<D>();
where
template <typename D> void Base::func();
is some helper function in Base.
Here is a solution that might work. Note that the assumption here is that you only make invocations with the right type:
struct Base {
virtual void foo(struct Visitor& visitor) = 0;
};
template <typename D>
struct Derived : Base {
virtual void foo (Visitor&v) override;
};
struct Visitor {
virtual ~Visitor() {} // Make this class polymorphic.
};
template <typename D>
struct Visitor_tmpl : public Visitor {
virtual void visit (Derived<D>*) const {/*Do whatever with T*/}
};
template <typename T, typename D>
struct FooVisitor : Visitor_tmpl<D> {
virtual void visit (Derived<D>*) const override {/*Do whatever with T*/}
};
template <typename D>
void Derived<D>::foo(Visitor&v) {
// In this function, D has been bound now to a specific type, so we downcast.
// It will throw an exception if not the right type.
dynamic_cast<Visitor_tmpl<D> &>(v).visit(this);
}
int main() {
Derived<int> d;
FooVisitor<double, int> v;
d.foo(v);
}
One possible solution was mentioned by Jarod42, namely to specify all possibly occuring types. Usually, however, you want to give a standard implementation taking a Base* as well, and overload this only when required.
struct Type1 {};
//...
struct TypeN {};
struct Visitor
{
virtual ~Visitor() {}
virtual void visit (Base*) const = 0;
virtual void visit (Derived<Type1>* d) const { visit(static_cast<Base*>(d)); };
//...
virtual void visit (Derived<TypeN>* d) const { visit(static_cast<Base*>(d)); };
};
struct FooVisitor : public Visitor
{
virtual void visit (Base* base) const override
{
std::cout<<"visiting base class."<<std::endl;
}
//further definitions for those types that require a special implementation
virtual void visit (Derived<TypeN>* d) const override
{
std::cout<<"visiting class of type Derived<TypeN>."<<std::endl;
}
};
DEMO
EDIT: Here is another possibility using basic double dispatch:
struct Visitor
{
virtual ~Visitor() {}
virtual void visit (Base*) const = 0;
};
struct FooVisitor : public Visitor
{
virtual void visit (Base* base) const override
{
if(Derived<TypeN>* d = dynamic_cast<Derived<TypeN>*>(base))
{
std::cout<<"visiting class of type Derived<TypeN>."<<std::endl;
}
else
{
std::cout<<"visiting base class."<<std::endl;
}
}
};
It releases you from declaring each possible variable type in the base class, but is probably less efficient than the previous solution.
This brute-force approach has some other disadvantages, which are collected in chapter 11 of Alexandrescu's book. You can also read there how to overcome these disadvantages by using a static dispatcher. Basically there you just enter once the types you want to consider for dispatching, and let the code create the above logic.
DEMO

Partial template specialization question

class FooInterface {
virtual void toggle() = 0;
};
template <class TYPE, class CONFIG>
class Foo : public FooInterface {
virtual void toggle();
TYPE value_;
};
template <>
void Foo<bool, class CONFIG>::toggle() {
if (CONFIG::canToggle())
value_ = !value_;
}
struct MyConfig {
static bool canToggle() {
return false;
}
};
int main() {
Foo<bool, MyConfig> foo;
}
That's an accurate approximation of what I'm dealing with. I basically want to have a specialized method for dealing with a TYPE, while keeping the CONFIG generic. So, for example, I might have a dozen different Foo::toggle() methods with specialized code handling specific TYPEs, but what's used from CONFIG will be consistent across all of those methods.
The problem is the previous code doesn't compile, along with several different combinations, and I'd appreciate some help finding a different solution or some workaround to make the current one work.
Edit: I should note that the previous code works without the CONFIG template parameter.
You need to partially specialise the whole class. You can't specialise individual member functions.
template <class CONFIG>
class Foo<bool, CONFIG> : public FooInterface
{
virtual void toggle();
bool value_;
};
template <class CONFIG>
inline void Foo<bool, CONFIG>::toggle()
{
if (CONFIG::canToggle())
value_ = !value_;
}
dispatch
template<class CONFIG, class C>
void toggle_impl(type<bool>, C &c) {
if (CONFIG::canToggle())
c.value_ = !c.value_;
}
template <class TYPE, class CONFIG>
class Foo : public FooInterface {
virtual void toggle() {
toggle_impl<CONFIG>(type<TYPE>(), *this);
}
TYPE value_;
};

Refactoring c++ template class based on template type

Given class Foo
template <typename T>
class Foo
{
public:
...other methods..
void bar()
{
...
m_impl.doSomething();
...
}
void fun()
{
...
m_impl.doSomethingElse();
...
}
void fubar()
{
...
}
private:
T m_impl;
};
I wanted to cater for situations where T is a boost::shared_ptr.
In this case the only change to class Foo is that it should invoke
m_impl->doSomething();
instead of
m_impl.doSomething();
I ended up defining FooPtr in the same header
template <typename T>
class FooPtr
{
public:
...other methods..
void bar()
{
...
m_pImpl->doSomething();
...
}
void fun()
{
...
m_pImpl->doSomethingElse();
...
}
void fubar()
{
...
}
private:
boost::shared_ptr<T> m_pImpl;
};
Now while the approach works for all classes that I want to use with Foo,
the problem is that I have a lot of duplicate code lying around and any changes
I make to Foo, I also have to make to FooPtr.
How can I refactor the code? E.g. Is there any way that I can determine at compile time if T is of type boost::shared_ptr, and then specialise just the bar and fun methods to invoke the -> operator?
Edit:
Thanks for all the answers so far! I just need some time to work through them all and see which solution is the best fit for our software.
Edit 2:
#Matthieu: This is the test code I was using
class FooImpl
{
public:
void doIt()
{
cout << "A" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Foo<FooImpl> foo;
foo.doSomething();
return 0;
}
Sylvain wrote a DRY solution, but I don't like abusing inheritance.
Using a wrapper class to uniformize the interface is easy, especially since pointer semantics work so well!
namespace details {
template <typename T>
struct FooDeducer {
typedef boost::optional<T> type;
};
template <typename T>
struct FooDeducer< T* > {
typedef T* type;
};
template <typename T>
struct FooDeducer< boost::shared_ptr<T> > {
typedef boost::shared_ptr<T> type;
};
} // namespace details
template <typename T>
class Foo {
public:
// methods
void doSomething() { impl->doIt(); }
private:
typedef typename details::FooDeducer<T>::type Type;
Type impl;
};
Here, relying on boost::optional which provides the OptionalPointee semantics, we nearly get the same behavior than pointers.
One point I'd like to emphasize though, is the difference in the copying behavior. boost::optional provides deep copy.
class A
{
public:
void doSomething() {}
};
template <typename T>
class Foo
{
public:
void bar()
{
Impl(m_impl).doSomething();
}
private:
template<typename P>
P& Impl(P* e)
{
return *e;
}
template<typename P>
P& Impl(std::shared_ptr<P> e)
{
return *e;
}
template<typename P>
P& Impl(P& e)
{
return e;
}
T m_impl;
};
You can write a caller class template, whose job is to call the function, either using syntax obj.f() or obj->f(), based on the type of obj.
Here is a small example that demonstrates this approach:
template<typename T>
struct caller
{
static void call(T &obj) { obj.f(); } //uses obj.f() syntax
};
template<typename T>
struct caller<T*>
{
static void call(T* obj) { obj->f(); } //uses obj->f() syntax
};
And this caller class template is used by this sample class:
template<typename T>
struct X
{
T obj;
X(T o) : obj(o) {}
void h()
{
caller<T>::call(obj); //this selects the appropriate syntax!
}
};
See this online running demo at ideone : http://www.ideone.com/H18n7
--
EDIT:
This is even more generic. Here you can even pass the function which you want to call in caller. Now caller is not hard-coded with the function to be called!
http://www.ideone.com/83H52
I really question whether you should be using a template here at all. Your template parameter has a very clear interface and therefore looks like you should just use an abstract base class.
Do you really need to have an instance? If you do need to change the way the object is represented, this should be done as a separate exercise and not part of the template that uses it.
You can introduce another intermediate template class, something like that:
template < typename T >
class FooBase
{
private:
T m_impl;
protected:
T& impl() { return m_impl; }
};
template < typename T >
class FooBase< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
protected:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo : protected FooBase< T >
{
public:
void bar()
{
impl().DoSomething();
}
};
Now, you only have to code the Foo class only once. And you can specialize it for other smart pointers type by doing partial specialization on FooBase.
Edit: You can also use composition instead of having an inheritance relationship between Foo and FooBase (in which case, I'd probably rename it to FooHelper or something like that).
template < typename T >
class FooHelper
{
private:
T m_impl;
public:
T& impl() { return m_impl; }
};
template < typename T >
class FooHelper< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
public:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo
{
private:
FooHelper< T > m_helper;
public:
void bar()
{
m_helper.impl().DoSomething();
}
};
You can use partial specialization.
template <typename T>
class Foo
{
public:
//...
};
template<typename T> class Foo<boost::shared_ptr<T>> {
//... implement specialization here
};