Virtual method with unspecialized template argument - c++

#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Currently I have code much like this one:
template <const uint32_t N>
using VectorN = array<double, N>;
template <const uint32_t N>
class ITransformable {
public:
virtual vector<VectorN<N>>& positions() = 0;
};
class SomeTransformer {
public:
template <const uint32_t N>
void operator()(ITransformable<N>& transformable) const {
/* implementation */
}
};
// Then I want to create interface like this.
template <const uint32_t N>
class ITransformer {
public:
virtual void operator()(ITransformable<N>& transformable) const = 0;
};
// And finally implement it for SomeTransformer:
//
// Notice that class is not template, this is intentional.
//
// class SomeTransformer : public ITransformer<N> {
// public:
// virtual void operator()(ITransformable<N>& transformable) const {
// /* implementation */
// }
// }
Actually, now it seems impossible to me. Otherwise this class would inherit
indefinite number of interface specializations...
But still, is it possible, at least for finite number of dimensions N?
template <template <typename> class C> seems to be related, but I can't figure out how to apply this.
EDIT
What I want is something like this:
class SomeTransformer :
public ITransformer<2>,
public ITransformer<3>,
public ITransformer<4>,
...,
public ITransformer<N> {
/* ... */
};
For any N ever used in code. This seems impossible, as I said.

You can achieve what you want or nearly that. Here's what I propose:
#include <type_traits>
#include <utility>
template<std::size_t N>
struct ITransformer {};
template<class T>
class SomeTransformer_h { };
template<std::size_t... Indices>
class SomeTransformer_h<
std::integer_sequence<std::size_t, Indices...>> :
public ITransformer<1 + Indices>... { };
template<std::size_t N>
class SomeTransformer : public SomeTransformer_h<
std::make_index_sequence<N>
> { };
int main() {
SomeTransformer<5> a;
ITransformer<1>& ref = a;
ITransformer<4>& ref2 = a;
ITransformer<5>& ref3 = a;
}
Now for any N it will make SomeTransformer inherit all ITransformer from 1 to N.

Since N is not declared anywhere, you cannot use it. You need something like:
class SomeTransformer : public ITransformer<5> {
public:
virtual void operator()(ITransformable<5>& transformable) const {
/* implementation */
}
};
or make it a template class:
template <uint32_t N>
class SomeTransformer : public ITransformer<N> {
public:
virtual void operator()(ITransformable<N>& transformable) const {
/* implementation */
}
};
UPDATE
There is no dynamic inheritance in C++. Therefore, what you want to achieve is not possible.

Related

Static polymorphism with constant template

I'd like to have a static polymorphism with the parent class having a template std::array size. This code works fine:
#include <iostream>
#include <array>
using namespace std;
template <size_t size>
class Message
{
public:
size_t GetSize() { return size; }
private:
std::array<uint8_t, size> data_{};
};
class Command : public Message<12>
{
public:
static const size_t kCmdSize{12};
private:
};
class Reply : public Message<16>
{
public:
static const size_t kCmdSize{12};
private:
};
int main()
{
Command cmd{};
Reply rpl{};
cout << "Size: " << cmd.GetSize() << "|" << rpl.GetSize() << endl;
return 0;
}
But I'm not a huge fan of magic numbers.
Is there any way to use a constant declared in the child class as the parameter to the parent class? Something like that:
class Command : public Message<kCmdSize>
{
public:
static const size_t kCmdSize{12};
private:
};
Using this directly attempts to use a variable from a class that doesn't exist yet.
Using C++14.
If you're fine with one extra layer of indirection, then you can use a "traits class" kind of solution:
#include <array>
#include <cstdint>
template <class T> struct MessageSize;
template <std::size_t size>
class Message {
public:
std::size_t GetSize() { return size; }
private:
std::array<std::uint8_t, size> data_{};
};
// Forward declare class for upcoming specialization.
class Command;
// Specialize message size for Command class.
template <> struct MessageSize<Command> {
static constexpr std::size_t size = 12;
};
class Command : public Message<MessageSize<Command>::size> { };
Note that in my example the Message class itself does not use the MessageSize one. You could do that as well, and have Command inherit from Message<Command> instead, but that would make your inheritance tree look a whole lot different (i.e. classes with the same message length wouldn't have the same base class anymore).
You could of course add another layer of indirection in there, where you inherit from e.g. MessageBase<Command> which in turn inherits from Message<MessageSize<Command>::size>.
That's common problem and there is solution used widely, e.g. in implementations of stream components of C++ library. The type definitions and constants related to concrete derived class became part of specialization for a trait class:
template <class T>
struct CommandTrait;
template <class T>
struct Message : public CommandTrait<T>
{
constexpr size_t GetSize() { return this->kCmdSize; } // or Message::kCmdSize, the same in this case
std::array<std::uint8_t, Message::size> data_{};
};
template <size_t _Sz, size_t _CSc = 12 >
struct MessageSize {
static constexpr std::size_t size = _Sz;
static constexpr size_t kCmdSize{ _CSc };
};
template <>
struct CommandTrait<struct Command> : MessageSize<12> {};
template <>
struct CommandTrait<class Reply> : MessageSize<16> {};
class Command : public Message<Command>
{
};
class Reply : public Message<Reply>
{
};
Note that this-> is important to suggest compiler that "kCmdSize" is a name depending on template's parameter. You need a template-dependant name (i.e. qualified for static use or using this-> for runtime). That tells compiler to expect that such name exist or will be existing in future, at time of instantiation. SHould not forget about possibility of using constexpr:
template <class T>
struct Message : public CommandTrait<T>
{
static constexpr size_t GetSize() { return Message::kCmdSize; }
std::array<std::uint8_t, GetSize()> data_{};
};
Trait class may have a common base, but generally type erasure is not required where such structs are used.
How about something like this?
Is there a concern to pass the number from your main-instance instead of letting it hang open in the class impl.
#include <iostream>
#include <array>
using namespace std;
template <size_t size>
class Message
{
public:
size_t GetSize() { return size; }
private:
std::array<uint8_t, size> data_{};
};
template<size_t N>
class Command : public Message<N>
{
public:
static const size_t kCmdSize{N};
private:
};
int main()
{
Command<12> cmd{};
cout << "Size: " << cmd.GetSize() << endl;
return 0;
}

Ignore template parameter

Is there a way in the code below to say that I don't care what the V parameter is in void watch(event<T, _> &e)
#include <stdlib.h>
#include <stdio.h>
enum events_a {
A_1,
A_2,
};
enum events_b {
B_1,
B_2,
};
template<typename T, T V>
class event {
public:
T id(void) {
return V;
}
};
template<typename T>
class event_loop {
public:
void watch(event<T, _> &e) {
};
};
class a1 : public event<enum events_a, A_2>
{
};
int
main (int argc, char *argv[])
{
a1 a;
printf("%d\n", a.id());
return 0;
}
What I'm trying to do is that users should be forced to subclass event<T,V> and be forced to give T and V.
However the subclass of event_loop<T>, specifically the method watch, should work with all event<T> regardless of their V.
I don't want to template just the watch function as I want the user to be forced to subclass event_loop.
Bonus achievement if I can somehow make sure all subclasses of event<T> have a unique V. Shooting for the stars... :D
Just create a template argument for it and ignore it.
template<typename T, typename Ignore>
class event_loop {
public:
void watch(event<T, Ignore> &e) {
};
};
You could also template just the function, if you want only the function to be templated
template<typename T>
class event_loop {
public:
template<typename Ignore>
void watch(event<T, Ignore> &e) {
};
};
You could specify a default argument for V and static assert like the way below:
enum events_a {
A_1 = 1,
A_2,
};
enum events_b {
B_1 = 1,
B_2,
};
template<typename T, T V = {}>
class event {
static_assert(V != 0, "You should Define a V");
public:
T id() {
return V;
}
};
template<typename T>
struct event_loop {
void watch(event<T> &e) {}
};
class a1 : public event<enum events_a, A_2> { };
Live Demo

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.

Get size of polymorphic object

I want to be able to get the size of polymorphic object. At the moment I got this:
struct Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
struct Derived : Base {
virtual std::size_t size() const {
return sizeof(*this);
}
};
Which is literally copy & paste. I want to do better. Suppose I really hate macros and CRTP seems like the only sensible approach. Let us give it a try:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type>
struct Sized : virtual SizedBase {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Base, Sized<Derived> {};
This looks much better, but sadly is ill-formed: Derived contains two final overriders for size() from Base and from Sized<Derived>. We can solve this by inheriting through Sized:
struct SizedBase {
virtual std::size_t size() const = 0;
};
template <typename Type, typename... SizedBases>
struct Sized : virtual SizedBase, SizedBases... {
std::size_t size() const override {
return sizeof(Type);
}
};
struct Base : Sized<Base> {};
struct Derived : Sized<Derived, Base> {};
This works as intended, however gets somewhat confusing in the event of multiple inheritance and prohibits altering accessibility/virtualness of bases.
So, is there a better way?
Not that anyone should really use this, but...
template <typename>
struct None1 {};
template <typename>
struct None2 {};
template <typename T>
struct PrivateBase { using Tpriv = T; using Tprot = None1<T>; using Tpub = None2<T>; };
template <typename T>
struct ProtectedBase { using Tpriv = None1<T>; using Tprot = T; using Tpub = None2<T>; };
template <typename T>
struct PublicBase { using Tpriv = None1<T>; using Tprot = None2<T>; using Tpub = T; };
template <typename K>
struct TriBase : private K::Tpriv, protected K::Tprot, public K::Tpub {};
template <typename T, typename ... Bases>
struct Sized : private Bases::Tpriv..., protected Bases::Tprot..., public Bases::Tpub...
{
virtual size_t size() { return sizeof(T); }
};
struct Foo : Sized<Foo> {};
struct X{};
struct Y{};
struct Bar : Sized<Bar, PrivateBase<X>, ProtectedBase<Y>, PublicBase<Foo>> {};
int main ()
{
Bar b;
Foo* f = &b;
X* x = &b; // error : private base
Y* y = &b; // error : protected base
}
Virtual inheritance is left as an exercise to the reader.
The order of base classes is not preserved, but you should not depend on it anyway.
Something that is a little bit more production-friendly can be implemented like this (this is a rough sketch):
#include <cstdlib>
#include <typeinfo>
#include <unordered_map>
#include <memory>
#include <iostream>
struct myinfo
{
size_t size;
// any other stuff
};
using TypeInfoRef = std::reference_wrapper<const std::type_info>;
struct Hasher
{
std::size_t operator()(TypeInfoRef code) const
{
return code.get().hash_code();
}
};
struct EqualTo
{
bool operator()(TypeInfoRef lhs, TypeInfoRef rhs) const
{
return lhs.get() == rhs.get();
}
};
static std::unordered_map<TypeInfoRef, myinfo, Hasher, EqualTo> typemap;
template <typename K>
struct typemap_initializer
{
typemap_initializer()
{
typemap[typeid(K)] = myinfo{sizeof(K)};
}
};
struct Base
{
virtual ~Base() {}
size_t size() { return typemap[typeid(*this)].size; }
template<typename K, typename... Arg>
friend K* alloc(Arg...);
private:
void* operator new(size_t sz) { return ::operator new(sz); }
};
template<typename K, typename... Arg>
K* alloc(Arg... arg)
{
static typemap_initializer<K> ti;
return new K(arg...);
}
struct Foo : Base {int a;};
struct Bar : Foo {int b; int c;};
int main ()
{
Foo* f = alloc<Foo>();
Bar* g = alloc<Bar>();
std::cout << f->size() << std::endl;
std::cout << g->size() << std::endl;
}
Of course one gives up the familiar Foo* foo = new Foo syntax, but in the era of ubiquitous std::make_shared<> this is not a big problem.

Use generalized template class in specialized template functions

I'm writing a wrapper for some benchmark code and want to execute the same code for every templated class type in an already templated function.
There is the benchmark class:
template<class T>
class Benchmark : public Interface, public T {
virtual void Execute();
}
And as class T I want to use a type that is basically only there for initializing class variables e.g.
template<class S>
struct GenericBench {
GenericBench();
S var1, var2, var3;
};
The question now: is it somehow possible to define a specialized function Execute for every mutation of GenericBench for this kind of class inheritance constelation?
template<>
void Benchmark<GenericBench>::Execute() {
// my benchmark code
}
A main call would then look something like this:
myBench->Execute<GenericBench<int>>();
The following code compiled and linked in g++
struct Interface { };
template<class T>
class Benchmark: public Interface, public T {
public:
virtual ~Benchmark() { }
virtual void Execute();
};
template<class S>
struct GenericBench {
GenericBench() { }
S var1, var2, var3;
};
// Specialization of the class
template<class S>
class Benchmark<GenericBench<S> >: public Interface, public GenericBench<S> {
public:
virtual ~Benchmark() { }
virtual void Execute() {
// do things
}
};
int main(int argc, char **argv) {
Benchmark<GenericBench<int> > myBench;
myBench.Execute();
}
Since you said that you want to define specialized responses on basis of type you are working on... making function template and then specializing it will help.
Following is an examples
(Apologies for not using example u provided.. I just want to show the approach. Let me know if it works for you)
template <class S> class myData {
public:
};
namespace mySpecializedFunction {
template<class P> void someFunction(P check) {std::cout<<"3333\n";return;}
template<> void someFunction(myData<int> check) {std::cout<<"4444\n";return;}
template<> void someFunction(myData<float> check) {std::cout<<"5555\n";return;}
}
template <class T> class myClass: public T {
public:
template <class Q> void someFunction( Q check) { mySpecializedFunction::someFunction(check); return ; }
};
And Using it like this...
myData<int> d1;
myData<float> d2;
myClass< myData<int> > c1;
c1.someFunction(d1);
myClass< myData<float> > c2;
c2.someFunction(d2);