I have a class template, that creates a class with two members:
template<typename coordinateType, typename ...DataTypes>
class Object{
public:
std::tuple<coordinateType, coordinateType, coordinateType> position;
std::tuple<std::vector<DataTypes>...> plantData;
};
The issue is, rather than calling
auto myObject = Object<float, int, int, int>();
for an instance of Object with 3 ints of data, I want to clean this up and use two separate templates, without the unrelated "float" as the first argument.
Is there a way to implement this class so that it would be the equivalent of:
auto myObject = Object<float>();
myObject.track<int, int, int>();
And if not, is it possible to separate those two template arguments in any way, or am I stuck with grouping them together?
if you change the caller side a little, you can make track to return a new class.
template<typename T, typename...Us>
struct Object{
std::tuple<T, T, T> position;
std::tuple<std::vector<Us>...> plantData;
};
// you can also give it a different name, here I use a specialization instead
template<typename T>
struct Object<T>{
template<typename...Us>
Object<T,Us...> track();
};
void foo(){
auto myObjectCreator = Object<float>();
auto myObject = myObjectCreator.track<int, int, int>();
}
https://godbolt.org/z/qhPrEaa96
If I understand you correctly, you'd like track<Ts> to append Ts to the list of DataTypes. This can be achieved like:
template<typename coordinateType, typename ...DataTypes>
class Object{
public:
template<typename... Ts>
Object<coordinateType, ...DataTypes, Ts>
track() { return {}; } // you might add proper ctor call, element copy via tuple::cat, etc.
std::tuple<coordinateType, coordinateType, coordinateType> position;
std::tuple<std::vector<DataTypes>...> plantData;
};
Related
How to define a class MultiInherit<MyTuple<X1,X2,...>> to inherit from X1,X2,... ?
I want to pass MyTuple<X1,X2,...> around to compose a new object type.
template <class... Xs> class MyTuple{};
template <class MyTupleXs> class MultiInherit : public All_Xs_in_MyTupleXs { //??
};
Here is its usage and MCVE (uncompilable):-
class B{public: int b;};
class C{public: int c;};
class BC : public MultiInherit<MyTuple<B,C>> {
public: void testCompile(){
this->b=this->c;
}
};
int main(){
}
Attempt 1
Below is the closest to what I wanted.
If I get raw-types (e.g. B,C) as template argumant rather than MyTuple<B,C>, it would be easy :-
(MCVE, compilable)
template <class... Xs> class MultiInherit : public Xs... {
};
class B{public: int b;};
class C{public: int c;};
class BC : public MultiInherit<B,C> {
public: void testCompile(){
this->b=this->c;
}
};
Reference: Variadic templates and multiple inheritance in c++11
This doesn't solve. I want to pass an encapsulated type MyTuple<B,C>, not the B,C.
Attempt 2
I thought about adding a new variadic typedef MyXs in MyTuple:-
template <class... Xs> class MyTuple{
public: using MyXs=Xs...;
};
template <class MyTupleXs> class MultiInherit : public MyTupleXs::MyXs {
};
Nevertheless, it seems to me that the language has no such feature.
(I am new to variadic template.)
Simple answer
You have to create a template specialization of MultiInherit. Let's look at the base case of MultiInherit:
template<class... Xs>
class MultiInherit : public Xs... {
// Stuff
};
Here, we take a bunch of types and inherit from them. But we can use a template specialization to unpack tuples:
// Specialization on MyTuple
template<class... Xs>
class MultiInherit<MyTuple<Xs...>> : public Xs... {
// Stuff
};
This allows you to do what you want. Given a MyTuple, you have a MultiInherit class that inherits from all the members.
More general case
Defining a type list. If you want to do things more generally, it'll be useful to do them based on templates representing type lists. We can define a template to represent a type list:
template<class...>
struct TypeList {};
Concatenating type lists. We can define more templates to concatenate type lists. ConcatLists is a function that takes two type lists, and returns a TypeList that concatenates them:
template<class... Xs, class... Ys>
TypeList<Xs..., Ys...> ConcatLists(TypeList<Xs...>, TypeList<Ys...>) {
return {};
}
We can use that to define a concat_t that does that automatically:
template<class TypeListA, class TypeListB>
using concat_t = decltype(ConcatLists(TypeListA{}, TypeListB{}));
Substituting MultiInherit for TypeList. We can also substitute one type for another type using template specializations.
// Base case
template<template<class...> class Replacement, class List>
struct SubstituteList;
template<
template<class...> class Replacement,
template<class...> class Original,
class... Xs>
struct SubstituteList<Replacement, Original<Xs...>> {
using type = Replacement<Xs...>;
};
template<template<class...> class Replacement, class List>
using substitute_list_t = typename SubstituteList<Replacement, List>::type;
This means that you can take a TypeList and replace it with a MultiInherit:
template<class ListOfTypes>
using MultiInheritFromTypeList = substitute_list_t<MultiInherit, ListOfTypes>;
Example usage. If you want to convert a TypeList to a MultiInherit:
using T1 = TypeList<int, char, bool>;
// T2 is MultiInherit<int, char, bool>;
using T2 = MultiInheritFromTypeList<T1>;
Example with concat. Or, if you want to concat multiple TypeLists and convert it to a MultiInherit:
using T1 = TypeList<int, char, bool>;
using T2 = TypeList<double, float>;
// T3 is MuliInherit<int, char, bool, double, float>
using T3 = MultiInheritFromTypeList<concat_t<T1, T2>>;
I have an issue I'm facing where I'm trying to build a factory function that,
given an ID and a type will return the correct (templated) subclass.
What this is trying to solve:
The id() values are sent across a network as soon as a connection is established, and specify to the receiver how a sequence of bytes are encoded. The receiver knows in advance the type T that it expects, but does not know how that type T is encoded on the wire until it gets this value. It also specifies how return values (of some type U, where U may or may not be the same type as T) should be marshalled when they are returned. This code is used generally, i.e. there are multiple senders/receivers that use/expect different types; the types used between a given sender/receiver pair are always fixed, however.
A basic sketch of the problem: we have a (simplified) base class that defines id()
template <typename T>
class foo
{
public:
virtual ~foo() { }
// Other methods
// This must return the same value for every type T
virtual std::uint8_t id() const noexcept = 0;
};
From there, we have some subclasses:
template <typename T>
class bar : public foo<T>
{
public:
std::uint8_t id() const noexcept override { return 1; }
};
template <typename T>
class quux : public foo<T>
{
public:
std::uint8_t id() const noexcept override { return 2; }
};
For the actual factory function, I need to store something that
erases the type (e.g. bar, quux) so that I can store the actual
creation function in a homogenous container.
Effectively, I want semantics that are roughly equivalent to:
struct creation_holder
{
// Obviously this cannot work, as we cannot have virtual template functions
template <typename T>
virtual foo<T>* build() const;
};
template <template <typename> class F>
struct create : public creation_holder
{
// As above
template <typename T>
foo<T>* build() const override
{
return new F<T>();
}
};
std::unordered_map<std::uint8_t, create*>& mapping()
{
static std::unordered_map<std::uint8_t, create*> m;
return m;
}
template <typename T, template <typename> class F>
bool register_foo(F<T> foo_subclass,
typename std::enable_if<std::is_base_of<foo<T>, F<T>>::value>::type* = 0)
{
auto& m = mapping();
const auto id = foo_subclass.id();
creation_holder* hold = new create<F>();
// insert into map if it's not already present
}
template <typename T>
foo<T>* from_id(std::uint8_t id)
{
const auto& m = mapping();
auto it = m.find(id);
if(it == m.end()) { return nullptr; }
auto c = it->second;
return c->build<T>();
}
I've played around with a number of ideas to try and get something with similar
semantics, but with no luck. Is there a way to do this (I don't care if the
implementation is significantly different).
Some utility types for passing around types and bundles of types:
template<class...Ts>
struct types_t {};
template<class...Ts>
constexpr types_t<Ts...> types{}; // C++14. In C++11, replace types<T> with types_t<T>{}. Then again, I don't use it.
template<class T>
struct tag_t {};
template<class T>
constexpr tag_t<T> tag{}; // C++14. In C++11, replace tag<T> with tag_t<T>{} below
Now we write a poly ifactory.
Here is an ifactory:
template<template<class...>class Z, class T>
struct ifactory {
virtual std::unique_ptr<Z<T>> tagged_build(tag_t<T>) const = 0;
virtual ~ifactory() {}
};
you pass in the tag you want to build and you get out an object. Pretty simple.
We then bundle them up (this would be easier in c++171, but you asked for c++11):
template<template<class...>class Z, class Types>
struct poly_ifactory_impl;
The one type case:
template<template<class...>class Z, class T>
struct poly_ifactory_impl<Z,types_t<T>>:
ifactory<Z, T>
{
using ifactory<Z, T>::tagged_build;
};
the 2+ case:
template<template<class...>class Z, class T0, class T1, class...Ts>
struct poly_ifactory_impl<Z,types_t<T0, T1, Ts...>>:
ifactory<Z, T0>,
poly_ifactory_impl<Z, types_t<T1, Ts...>>
{
using ifactory<Z, T0>::tagged_build;
using poly_ifactory_impl<Z, types_t<T1, Ts...>>::tagged_build;
};
We import the tagged_build method down into the derived classes. This means that the most-derived poly_ifactory_impl has all of the tagged_build methods in the same overload set. We'll use this to dispatch to them.
Then we wrap it up pretty:
template<template<class...>class Z, class Types>
struct poly_ifactory:
poly_ifactory_impl<Z, Types>
{
template<class T>
std::unique_ptr<Z<T>> build() const {
return this->tagged_build(tag<T>);
}
};
notice I'm returning a unique_ptr; returing a raw T* from a factory method is code smell.
Someone with a poly_ifactory<?> just does a ->build<T>() and ignores the tagged_ overloads (unless they want them; I leave them exposed). Each tagged_build is virtual, but build<T> is not. This is how we emulate a virtual template function.
This handles the interface. At the other end we don't want to have to implement each build(tag_t<T>) manually. We can solve this with the CRTP.
template<class D, class Base, template<class...>class Z, class T>
struct factory_impl : Base {
virtual std::unique_ptr<Z<T>> tagged_build( tag_t<T> ) const override final {
return static_cast<D const*>(this)->build_impl( tag<T> );
}
using Base::build;
};
template<class D, class Base, template<class...>class Z, class Types>
struct poly_factory_impl;
the 1 type case:
template<class D, class Base, template<class...>class Z, class T0>
struct poly_factory_impl<D, Base, Z, types_t<T0>> :
factory_impl<D, Base, Z, T0>
{
using factory_impl<D, Base, Z, T0>::tagged_build;
};
the 2+ type case:
template<class D, class Base, template<class...>class Z, class T0, class T1, class...Ts>
struct poly_factory_impl<D, Base, Z, types_t<T0, T1, Ts...>> :
factory_impl<D, poly_factory_impl<D, Base, Z, types_t<T1, Ts...>>, Z, T0>
{
using factory_impl<D, poly_factory_impl<D, Base, Z, types_t<T1, Ts...>>, Z, T0>::tagged_build;
};
what this does is write a series of tagged_build(tag_t<T>) overloads of the ifactory methods, and redirects them to D::build_impl(tag_t<T>), where D is a theoretical derived type.
The fancy "pass Base around" exists to avoid having to use virtual inheritance. We inherit linearly, each step implementing one tagged_build(tag<T>) overload. All of them dispatch downward non-virtually using CRTP.
Use looks like:
struct bar {};
using my_types = types_t<int, double, bar>;
template<class T>
using vec = std::vector<T>;
using my_ifactory = poly_ifactory< vec, my_types >;
struct my_factory :
poly_factory_impl< my_factory, my_ifactory, vec, my_types >
{
template<class T>
std::unique_ptr< vec<T> > build_impl( tag_t<T> ) const {
return std::make_unique< std::vector<T> >( sizeof(T) );
// above is C++14; in C++11, use:
// return std::unique_ptr<vec<T>>( new vec<T>(sizeof(T)) );
}
};
and an instance of my_factory satisfies the my_ifactory interface.
In this case, we create a unique ptr to a vector of T with a number of elements equal to sizeof(T). It is just a toy.
Live example.
The pseudo code design.
The interface has a
template<class T> R build
function. It dispatches to
virtual R tagged_build(tag_t<T>) = 0;
methods.
The Ts in question are extracted from a types_t<Ts...> list. Only those types are supported.
On the implementation side, we create a linear inheritance of CRTP helpers. Each inherits from the last, and overrides a virtual R tagged_build(tag_t<T>).
The implementation of tagged_build uses CRTP to cast the this pointer to a more-derived class and call build_impl(tag<T>) on it. This is an example of non-runtime polymorphism.
So calls go build<T> to virtual tagged_build(tag_t<T>) to build_impl(tag<T>). Users just interact with one template; implementors just implement one template. The glue in the middle -- the virtual tagged_build -- is generated from a types_t list of types.
This is about 100 lines of "glue" or helper code, and in exchange we get effectively virtual template methods.
1 in c++17 this becomes:
template<template<class...>class Z, class...Ts>
struct poly_ifactory_impl<Z,types_t<Ts...>>:
ifactory<Z, Ts>...
{
using ifactory<Z, Ts>::tagged_build...;
};
which is much simpler and clearer.
Finally, you can do something vaguely like this without a central list of types. If you know both the caller and the callee know the type you could pass a typeid or typeindex into the ifactory, pass a void* or something similar out over the virtual dispatch mechanism, and cast/check for null/do a lookup in a map to types.
The internal implementation would look similar to this one, but you wouldn't have to publish types_t as part of your formal (or binary) interface.
Externally, you would have to "just know" what types are supported. At runtime, you might get a null smart (or dumb, ick) pointer out if you pass in an unsupported type.
With a bit of care you could even do both. Expose an efficient, safe mechanism to get compile-time known types applied to a template. Also expose a "try" based interface that both uses the efficient compile-time known system (if the type matches) and falls back on the inefficient runtime checked on. You might do this for esoteric backwards binary compatibility reasons (so new software can connect over an obsolete interface to new or old API implementations and handle having an old API implementation dynamically).
But at that point, have you considered using COM?
How to define method signature so it will accept same number of arguments as variadic template class definition? For example how to define an Array class:
template<typename T, int... shape>
class Array
{
public:
T& operator () (???);
};
So you will be able to call it like this:
Array<int, 3, 4, 5> a;
a(1, 2, 3) = 2;
template<class T, int...Shape>
class Array {
template<int>using index_t=int; // can change this
public:
T& operator()(index_t<Shape>... is);
};
or:
template<class T, int...Shape>
class Array {
public:
T& operator()(decltype(Shape)... is);
};
or:
template<class T, int...Shape>
class Array {
public:
T& operator()(decltype(Shape, int())... is);
};
if you want to be able to change the type of the parameter to be different than Shape.
I find the decltype harder to understand a touch than the using, especially if you want to change the type of the parameter to be different than int.
Another approach:
template<class T, int...Shape>
class Array {
public:
template<class...Args,class=typename std::enable_if<sizeof...(Args)==sizeof...(Shape)>::type>
T& operator()(Args&&... is);
};
which uses SFINAE. It does not enforce that the Args are integer types however. We could add another clause if we wanted to (that all of the Args are convertible to int, say).
Yet another approach is to have your operator() take a package of values, like a std::array<sizeof...(Shape), int>. Callers would have to:
Array<double, 3,2,1> arr;
arr({0,0,0});
use a set of {}s.
A final approach would be:
template<class T, int...Shape>
class Array {
public:
template<class...Args>
auto operator()(Args&&... is) {
static_assert( sizeof...(Args)==sizeof...(Shapes), "wrong number of array indexes" );
}
};
where we accept anything, then generate errors if it is the wrong number of arguments. This generates very clean errors, but does not do proper SFINAE operator overloading.
I would recommend tag dispatching, but I don't see a way to make it much cleaner than the SFINAE solution, with the extra decltype and all, or better error messages than the static_assert version on the other hand.
I assume you want your arguments to be all of the same type, probably using an integer type (I'll just use int). An easy approach is to leverage the parameter pack you already have:
template <int>
struct shape_helper { typedef int type; };
template <typename T, int... Shape>
class Array
{
public:
T& operator()(typename shape_helper<Shape>::type...);
};
I have some code that compiles and works fine in C++ (as long as I forward declare the generic template class, then the specialized instance, and then define the generic template class - see inheriting from class of specialized self?). When I try to use SWIG to add C# bindings to the class, however, it either crashes SWIG or doesn't include the methods from the inherited class. I believe this is only possible in C++11, but I'm not sure as I haven't tried this with an older compiler.
Here's a toy example:
template <typename T, int N = 0> class A;
template <typename T> class A<T, 0>
{
public:
A() : mFoo(NULL) {}
virtual ~A() {}
T* getFoo() { return mFoo; }
protected:
T* mFoo;
};
template <typename T, int N = 0> class A : public A<T, 0>
{
public:
A() : A<T, 0>(), mBar(N) {}
virtual ~A() {}
int getBar() const { return mBar; }
protected:
int mBar;
};
In a program, I can then instantiate an instance of A<char,10> (for example), and have access to mFoo and mBar, or just instantiate an instance of A and only have access to mFoo. I can also use methods with parameters like
void baz(A<T, 0>* anyA)
and the method will accept A<T, 0> or A<T, n> instances.
For context and explanation, this pattern works well for containers that can be either dynamic or fixed size. If they are dynamic, you can just instantiate it as a A<T, 0> and not have the overhead of inheritance, etc. or you can have a fixed-sized container (A<T, N> where N > 0) that does use inheritance, but has access to all the "base" class methods, can override them as needed, and still be accepted as a parameter for methods that accept either dynamic or fixed-sized instances of the container.
However, when I try to use SWIG so that I can use this class in other languages, I run into issues.
At first, I tried something like:
%template(tA) A<char, 0>;
but this causes SWIG to crash (at least in version 3.0.0 that I'm currently using).
Next, thinking that, like all template inheritance in SWIG, I need to have an existing template for the base class as well as the inheritor class (if both are templated anyway). So I tried
%template(tABase) A<char, 0>;
%template(tA) A<char>;
This also causes SWIG to crash.
So, I tried to be a little clever and take advantage of SWIGS ability to use a "nameless" template for classes that are inherited from and did something like:
%template() A<char, 0>;
%template(tA) A<char>;
This avoids the crash and I get an output of the tA class, but it only has the methods, etc. from the inheritor class A<T, N> and does not actually inherit from the A<char, 0> specialized template instance that it needs to and thus I have no access to all the methods and data in the "base" class of A<char, 0>.
Has anyone else tried to get SWIG to handle this? Successfully? Is there a command line param that I can pass to SWIG that will make things work (and stop it from crashing)?
The easiest way I can see to solve your problem is to stop being so fancy that you confuse the other languages, by being fancier within C++:
template<typename T>
struct A0_impl;
template<typename T, typename N>
struct A_impl;
template<typename T, int N>
struct A_helper {
typedef A_impl<T,N> type;
};
template<typename T>
struct A_helper<T,0> {
typedef A0_impl<T> type;
};
template<typename T, int N=0>
using A = typename A_helper<T,N>::type;
template<typename T>
struct A0_impl {
A0_impl() : mFoo(nullptr) {}
virtual ~A0_impl() {}
T* getFoo() { return mFoo; }
private:
T* mFoo;
};
template<typename T, typename N>
struct A_impl:A0_impl<T> {
A_impl() : A0_impl<T>(), mBar(N) {}
virtual ~A_impl() {}
int getBar() const { return mBar; }
protected:
int mBar;
};
template<typename T>
struct A_impl<T,0>:A0_impl<T> {
A_impl() : A0_impl<T>() {}
virtual ~A_impl() {}
// possibly inherit other constructors from A0_impl
};
this gives you C++ code that behaves nearly exactly like your version, but does away with that descend-from-specialization issue that you believe is causing your problems.
Basically I replaced your A<T,0> specialization with A0_impl, and the template alias A<T,N> now maps to either A_impl<T,N> or A0_impl<T> depending on if N is 0 or not.
The A template alias is optional, as you could instead have A0_impl be called AnySizedA and A_impl be called FixedSizeA, and instead of specializing A<T,0> to do something simply ban it.
Inspired of boost::operators I thought the Barton-Nackman idiom could be used to implement from trival member methods.
Following is what I have tried (does not compile)
template<typename T>
class impl_get_set {
typename T::storage_type get() const {
return static_cast<const T *>(this)->data_;
}
void set(typename T::storage_type d) {
*static_cast<T *>(this)->data_ = d;
}
};
struct A : public impl_get_set<A> {
typedef int storage_type;
storage_type data_;
};
struct B : public impl_get_set<B> {
typedef double storage_type;
storage_type data_;
};
As this does not compile there is clearly something I have got wrong. My question is, can this be done, and if so how?
When using CRTP, you have to take care when designing the base, i.e. impl_get_set in this case. When the derived class instantiates the base specialization, e.g. as done with A: public impl_get_set<A>, the A class is still incomplete.
However the definition of impl_get_set uses typename T::storage_type in a member function declaration. This use requires a complete T. The C++03 way to solve that is to make any associated type that the CRTP base may need part of the class template parameters:
template<typename Derived, typename StorageType>
struct get_set {
typedef StorageType storage_type;
// It's possible to define those inline as before where
// Derived will be complete in the body -- which is why
// CRTP is possible at all in the first place
storage_type get() const;
void set(storage_type s);
// Convenience for clients:
protected:
typedef get_set get_set_base;
};
struct A: get_set<A, int> {
// Member type is inherited
storage_type data;
};
template<typename T>
struct B: get_set<B<T>, double> {
// Incorrect, storage_type is dependent
// storage_type data;
// First possibility, storage_type is
// still inherited although dependent
// typename B::storage_type data;
// Second possibility, convenient if
// storage_type is used multiple times
using typename B::get_set_base::storage_type;
storage_type data;
void foo(storage_type s);
};
boost::iterator_facade is a good example of a well-written C++03-style CRTP wrapper from Boost.Iterator.
C++11 gives another way to write a CRTP base thanks in part to default template arguments for function templates. By making the derived class parameter dependent again, we can use it as if it were complete -- it will only be examined when the member function template of the CRTP base specialization is instantiated, once it is complete, and not when the CRTP base specialization itself is:
// Identity metafunction that accepts any dummy additional
// parameters
template<typename T, typename... Dependent>
struct depend_on { using type = T; };
// DependOn<T, D> is the same as using T directly, except that
// it possibly is dependent on D
template<typename t, typename... D>
using DependOn = typename depend_on<T, D...>::type;
template<typename Derived>
struct get_set {
template<
// Dummy parameter to force dependent type
typename D = void
, typename Storage = typename DependOn<Derived, D>::storage_type
>
Storage get() const
{
// Nothing to change, Derived still complete here
}
};
In fact, for your example get_set arguably doesn't need to care about whether a member type is present or not:
// std::declval is from <utility>
template<
typename D = void
, typename Self = DependOn<Derived, D>
>
auto get() const
-> decltype( std::declval<Self const&>().data )
{ return static_cast<Derived const&>(*this).data; }
This implementation of get has subtly different semantics from your own in that it returns a reference to data but that's on purpose.
The best I could figure out is that you're in a chicken/egg problem.
struct A uses impl_get_set as base, that forces instantiation. But at that point A is incomplete, its contents not yet available. Therefore T::storage_type fails to resolve to anything.
The only workaround I found was to just have another template param for impl_get_set and pass it from above. So go the opposite direction:
template<typename T, typename ST>
class impl_get_set {
public:
typedef ST storage_type;
storage_type get() const {
return static_cast<const T *>(this)->data_;
}
void set(storage_type d) {
*static_cast<T *>(this)->data_ = d;
}
};
struct A : public impl_get_set<A, int> {
storage_type data_;
};
(A is currently not used in the base, I left it in for possible other plans)