I've got a bunch of similar interfaces. I have a class template that can implement those interfaces and implement most operations that are common to those interfaces. As a result, I use a mixin on top of those interfaces.
Unfortunately, some of those interfaces are missing some of the common methods.
struct Intf1
{
virtual void f() = 0;
};
struct Intf2 {}; // Missing f.
I want to apply a mixin
template <class T>
struct Mixin
: public T
{
virtual void f() override {};
};
to a base, exactly if the base class declares a virtual method f that the mixin overrides. So, basically I am looking for some meta-programming technique
template <template <class> class Mixin, class T> using Magic = ...;
such that Magic<Mixin, Intf1> is Mixin<Intf1> and Magic<Mixin, Intf2> is Intf2.
At the moment, I am using a separate trait to check whether a method is available in the base class, but this solution has some problems:
I have to reiterate the function signature.
I do not definitely know whether the method is virtual (though it seems, this can be done).
Due to type conversion / const-ness, I may try to override a method that does not match my method's signature perfectly.
I was hoping that there might be a better solution. If my Mixin was a class that caused a substitution failure, I'd try something like this: Godbolt.
it's impossible to detect if a function is a virtual function.
but if all pure virtual functions of T is overridden by Mixin, it works:
#include <type_traits>
struct Intf1{
virtual void f() = 0;
};
struct Intf2 {};
struct Intf3{
virtual void f2() = 0;
};
template <class T>
struct Mixin : public T{
virtual void f() {}; // don't mark 'override', it will break SFINAE.
};
template<template<typename>class MixIn, typename T, typename = void>
struct Applier{
typedef T type;
};
template<template<typename>class MixIn, typename T>
struct Applier<MixIn, T, typename std::enable_if<std::is_abstract<T>::value && std::is_abstract<MixIn<T>>::value>::type>{
typedef T type;
};
template<template<typename>class MixIn, typename T>
struct Applier<MixIn, T, typename std::enable_if<std::is_abstract<T>::value && !std::is_abstract<MixIn<T>>::value>::type>{
typedef MixIn<T> type;
};
template<template<typename>class MixIn, typename T>
using applier_t = typename Applier<MixIn, T>::type;
static_assert(std::is_same<applier_t<Mixin, Intf1>, Mixin<Intf1>>::value, "overridden");
static_assert(std::is_same<applier_t<Mixin, Intf2>, Intf2>::value, "not abstract");
static_assert(std::is_same<applier_t<Mixin, Intf3>, Intf3>::value, "not overridden");
Related
I'm trying to check if a class that I'm templating is inheriting from another templated class, but I can't find the correct way to do it.
Right now I have the following:
#include <iostream>
template <typename MemberType, typename InterfaceType>
class Combination : public InterfaceType
{
public:
Combination();
virtual ~Combination();
private:
MemberType* pointer;
};
class MyInterface {};
class MyMember {};
class MyCombination : public Combination<MyMember, MyInterface>
{
};
int main()
{
static_assert(std::is_base_of_v<Combination<MyMember, MyInterface>, MyCombination>);
std::cout << "hello";
}
Which is working fine, but in the place this template is placed, I don't have access to the template parameters definitions, and this should be quite generic. What I'd like is to test for the MyCombination class to inherit from a generic Combination without taking into account the template arguments, something like this:
static_assert(std::is_base_of_v<Combination, MyCombination>);
or
static_assert(std::is_base_of_v<Combination<whatever, whatever>, MyCombination>);
Would you know how to check for this?
In this case I can't use boost libraries or other external libraries.
Thanks!
EDIT: I don't have access to modify the Combination class, and what I can change is the assert and the My* classes.
This can easily be done with the C++20 concepts. Note that it requires a derived class to have exactly one public instantiated base class.
template <typename, typename InterfaceType>
class Combination : public InterfaceType {};
class MyInterface {};
class MyMember {};
class MyCombination : public Combination<MyMember, MyInterface> {};
template<class Derived, template<class...> class Base>
concept derived_from_template = requires (Derived& d) {
[]<typename... Ts>(Base<Ts...>&) {}(d);
};
static_assert(derived_from_template<MyCombination, Combination>);
Demo
The equivalent C++17 alternative would be
#include <type_traits>
template<template<class...> class Base, typename... Ts>
void test(Base<Ts...>&);
template<template<class...> class, class, class = void>
constexpr bool is_template_base_of = false;
template<template<class...> class Base, class Derived>
constexpr bool is_template_base_of<Base, Derived,
std::void_t<decltype(test<Base>(std::declval<Derived&>()))>> = true;
static_assert(is_template_base_of<Combination, MyCombination>);
I have a template hierarchy, and I want it to have clone() function depending on whether template type is copy-constructible. As a first step I want to begin with additional parameter bool Clonable:
template<class T, bool Clonable>
class Base {
T t;
void foo();
virtual void bar();
virtual unique_ptr<Base> clone() const = 0; //should be only for Clonable=true
};
template<class T, bool Clonable>
class Derived : public Base<T, Clonable> {
virtual void bar() override;
virtual unique_ptr<Base> clone() const override; ////should be only for Clonable=true
};
Unfortunately, instantiation of virtual functions does not depend on whether they are called or not. So I suppose that I should go with partial specialization. However, straightforward way leads to very much of code duplication. Could anyone recommend the way to achieve this with minimum code duplication?
Unfortunately, contrary to a few of the comments here, SFINAE cannot help you here. That's because a non-template member of a template class is not considered a template, and therefore cannot be SFINAE'ed out: http://coliru.stacked-crooked.com/a/258e20a0293d93f0. The standard approach to solve this would typically to make it a template in a trivial way:
template <class U = T, std::enable_if ... >
virtual std::unique_ptr<Base> clone() const = 0;
But virtual functions can't be templates, so this doesn't work.
The way to avoid repetition in this case is to inherit from a class that conditionally has the member:
template <class Base, bool Cloneable>
struct CloneInterface;
template <class Base>
struct CloneInterface<Base, false> {};
template <class Base>
struct CloneInterface<Base, true> {
virtual unique_ptr<Base> clone() const = 0;
}
And now you just inherit:
template<class T, bool Clonable>
class Base : CloneInterface<Base<T, Clonable>, Clonable> {
T t;
void foo();
virtual void bar();
};
Notice that we inherit from a base class that is templated on the derived (the derived class in question is called Base, to make things more confusing :-) ). This technique is called CRTP and it is quite powerful as it can inject interface and implementations into classes, and as you can see can do so conditionally as well.
To get the implementation, we use CRTP again:
template <class T, bool Clonable, class D>
struct BaseHelper;
template <class T, class D>
struct BaseHelper<T, false, D> : Base<T, false> {};
template <class T, class D>
struct BaseHelper<T, true, D> : Base<T, true> {
unique_ptr<Base<T, true>> clone() override { return make_unique<D>(static_cast<D&>(*this)); }
};
template<class T, bool Clonable>
class Derived : public BaseHelper<T, Clonable, Derived<T, Clonable>> {
virtual void bar() override;
};
Suppose I have set of classes inheriting from a single superclass S:
class S{ ... };
class C1 : public S{ ... };
class C2 : public S{ ... };
Then suppose I have a templated method:
template<class T> void foo(T* instance);
I would like to statically check that foo is never called providing an instance of the superclass but only called providing one of the (concrete) subclasses (e.g. explicitly calling foo<C1>(x) for instance)
Is this possible?
First we can write a trait to check if T is derived from S, but not S:
template <class Base, class Derived>
using is_strict_base =
std::integral_constant<bool,
std::is_base_of<Base,Derived>::value &&
!std::is_same<Base,typename std::remove_cv<Derived>::type>::value>;
You can use std::enable_if to use this trait:
template<class T>
typename std::enable_if<is_strict_base<S,T>::value>::type
foo(T* instance)
{}
With C++14 you can use std::enable_if_t to make it a bit prettier:
template<class T>
std::enable_if_t<is_strict_base<S,T>::value>
foo(T* instance)
{}
Another option is to use static_assert:
template<class T>
void foo(T* instance)
{
static_assert(is_strict_base<S,T>::value,
"T must be derived from S, but not S");
}
This gives you a nicer error, but I personally believe that type constraints for a function belong in the declaration.
Here is my situation:
Base class, no templated type:
struct Thing
{
} ;
Templated class, extends that very base class
template <typename T> struct VertexWriter : public Thing
{
template <typename S>
bool intersects( S* otherThing )
{
// has a body, returns T or F
}
} ;
Derived class, CONCRETE type (no template)
struct Rocket : VertexWriter<VertexPNCT>
{
template <typename S>
bool intersects( S* otherThing ) ; // WANTS TO OVERRIDE
// implementation in VertexWriter<T>
} ;
But template typename<S> bool VertexWriter<T>::intersects cannot be marked virtual, because it is a template class.
There are many classes that derive from the VertexWriter<VertexPNCT> specialization, so template specializing VertexWriter<VertexPNCT> would not work.
So the normal thing to do is to provide a template specialization.
But Rocket specifies it is a VertexWriter<VertexPNCT>, so it is no longer a template class. Can it specialize OR override intersects as if it were a virtual function?
No, as you've stated you cannot use virtual functions, which would provide runtime polymorphism.
That said, depending on what leeway you have on changing the layout of your classes, you might be able to do something using CRTP.
template <typename T, typename Derived> struct VertexWriter : public Thing
{
template <typename S>
bool intersects( S* otherThing )
{
return static_cast<Derived*>(this)->insersects_impl(otherThing);
}
template<typename S>
bool insersects_impl( S* otherThing)
{
// Whatever
}
} ;
struct Rocket : VertexWriter<VertexPNCT, Rocket>
{
template <typename S>
bool intersects_impl( S* otherThing ) { ... } // WANTS TO OVERRIDE
// implementation in VertexWriter<T>
} ;
The base implementation of intersects simply forwards to the CRTP function. If the derived class overrides it, it'll use the override, but otherwise it'll fall back the default. Note, this does complicate your class hierarchy, but might accomplish what you're looking for.
No, you cannot.
Templated member functions cannot be virtual.
It doesn't matter whether VertexWriter is templated, specialized, or a normal class.
You could template VertexWriter on S and make intersects a virtual function of that class template
template <typename T, typename S> struct VertexWriter : public Thing
{
virtual bool intersects( S* otherThing )
{
// has a body, returns T or F
}
} ;
Now you can override intersects in a derived class
template<typename S>
struct Rocket : VertexWriter<VertexPNCT, S>
{
virtual bool intersects( S* otherThing ) ; // WANTS TO OVERRIDE
// implementation in VertexWriter<T>
}
class Foo1: public IFoo
{
public:
template <class T>
std::vector<T> foo()
{
return std::vector<T>();
}
};
class Foo2: public IFoo
{
public:
template <class T>
std::vector<T> foo()
{
return std::vector<T>();
}
};
How can I define a common interface class for the two implementations above, such that std::vector<T> foo() is defined for this interface? Ignore that the implementations of the functions are identical.
UPDATE:
I'm writing a Container class which represents data which is sent to me via a C api.
An instance of my Container will store data of a given type, such as Container<int>, Container<std::string> and Container<Foo>.
The C api returns the data in a very awkward manner and it is possible that this will change in the future. It is possible that I can copy the data into for example std::list or std::vector, but since so much data is passed from the C api it is not known yet if this will be OK or not.
For this reason, the Container class should be independent of how the data is actually stored. I achieve this using Getter and Setter classes which I pass into the contructor, as follows:
Container<int>(Getter1<int>(uglyCApiContainer),Setter1<int>(uglyCApiContainer));
Therefore if I abandon Getter1 and Getter2 which deals with how the C api stores data, I will only need to change the creation of Containers.
However, I have a problem with this design. The type Foo.
Foo is a complex type which contains itself a set of Containers. At the moment it looks something like this:
class Foo
{
public:
...
template <class V>
Container<V> getMember(std::string& memberName)
};
So a given Foo can have a set of containers of different types. The types of these members are know to me in advance since they are stored in a model. Foo is currently a wrapper around the ugly C api memory implementation, but I would like to separate also for Foo the memory representation as I've done for the Container.
I'm not sure how to make Foo free of its memory implementation. One idea I had was to make getMember virtual so as to introduce perhaps different implementations but this isnt possible for templated functions.
Here's a solution using tag dispatching and virtual inheritance:
#include <vector>
template<typename T> struct tag {};
template<typename T> class IFooImpl {
public:
virtual std::vector<T> getImpl(tag<T>) = 0;
};
class IFoo: public virtual IFooImpl<char>, virtual IFooImpl<int>
{
public:
template<typename T> std::vector<T> get() {
return static_cast<IFooImpl<T> *>(this)->getImpl(tag<T>{});
}
};
template<typename T>
class FooImpl: public virtual IFooImpl<T> {
public:
std::vector<T> getImpl(tag<T>) { return {}; }
};
class Foo: public IFoo, FooImpl<char>, FooImpl<int> {
};
int main() {
Foo().get<char>();
}
There's a little bit of repetition where the supported types are covered (here char and int), but that can be avoided with variadic template inheritance:
#include <vector>
template<typename T> struct tag {};
template<template<typename> class C, typename... Types> class Inherit {};
template<template<typename> class C, typename T, typename... Rest>
class Inherit<C, T, Rest...>: public C<T>, Inherit<C, Rest...> {};
template<typename T> class IFooImplV {
public:
virtual std::vector<T> getImpl(tag<T>) = 0;
};
template<typename T> class IFooImpl: public virtual IFooImplV<T> {};
template<typename... Types> class IFoo: public Inherit<IFooImpl, Types...> {
public:
template<typename T> std::vector<T> get() {
return static_cast<IFooImpl<T> *>(this)->getImpl(tag<T>{});
}
};
template<typename T> class FooImpl: public IFooImpl<T> {
public:
std::vector<T> getImpl(tag<T>) { return {}; }
};
template<typename... Types> class FooMulti:
public IFoo<Types...>, Inherit<FooImpl, Types...> {};
class Foo: public FooMulti<char, int> {};
int main() {
Foo().get<char>();
}