Autodetect typeparameters of Base class - c++

I have had the following code which worked fine:
template<typename T>
class Base {
virtual void call(T) = 0;
};
class Derived : public Base<int> {
void call(int);
}
template<typename T>
void registerBase(const Base<T>& ref) {}
This approach can autodetect the type T as int when called as registerBase(Derived()). The problem comes when I switch to shared_ptr:
template<typename T, typename Q>
void registerBase(shared_ptr<Q> ptr) {
static_assert(is_base_of<Base<T>, Q>::value, "Have to supply a type extending Base<...>");
}
I can protect from illegal type but I can't seem to autodetect the type T. Is there some trick I can use to automatically down-cast the shared_ptr to Base<T> so template-deduction works? Or is there another way to find the typename T?
PS: In case Q extends multiply Base<T> I want to error (autodeduction should fail).

There are probably a gazillion ways to do this. Here's one:
template<class T>
T helper(const Base<T> &); // not defined
template<class Q>
using base_param = decltype(helper(std::declval<Q>()));
In actual code, you'd probably want to put helper in a details namespace (and probably also change the names).
This will break if you have an odd case of T being a type that can't be returned - e.g., an array type. It's easily fixable by altering helper's return type to, e.g., identity<T> and then also altering the definition of base_param accordingly.

Related

derived method receiving const char * shadows base method receiving char [duplicate]

This has me wondering. Suppose I have :
class Base
{
public:
template<typename T>
void foo(T& varT)
{
//
}
template<typename T, typename U>
void foo(T& varT, U& varU)
{
//
}
};
class Child : public Base
{
public:
template<typename T, typename U, typename Z>
void foo(T& varT, U& varU, Z& varZ)
{
//
}
};
Now when I try this:
Child c;
char cVar;
int iVar;
float fVar;
c.foo(cVar);
c.foo<int>(cVar);
c.template foo<int>(cVar);
None of the calls work. They are always shadowed with error 'No matching member function for call'. Can anybody point me to a way to resolve this? I read in the standard that derived objects shadow template functions inherited but the standard explicitly said that the parameter list must be the same if they are shadowed.
Appreciate the help.
Hiding base members always happens when you have a name in a derived class that is present in a base class. The basic reason is that it is desirable to guard derived class uses against changes in the base class: assuming names from bases were not hidden, if a new overload in a base class is added a working look-up to a derived member may be hijacked to rather refer to the base class without any indication in the derived class that something may happen in the base class. If you mean to make the base members available, you can use a using declaration:
class Child : public Base
{
public:
using Base::foo; // declare that you want look up members from the base class
template<typename T, typename U, typename Z>
void foo(T& varT, U& varU, Z& varZ)
{
//
}
};
In your code you had three calls:
c.foo(cVar) works with the using declaration.
c.foo<int>(cVar) doesn't work even with the using declaration because you can't bind a non-const reference to int to a char lvalue. Using c.foo<char>(cVar) would work.
c.template foo<int>(cVar) suffers from the same problem. Since c is clearly not a dependent name, there is no need at all to use template in this context.
Without the using declaration you can call the member by qualifying the call explicitly, e.g.:
c.Base::foo(cVar);
You need this:
http://en.cppreference.com/w/cpp/language/using_declaration
Add to Child's definition:
using Base::foo;

C++ using declaration for parameter pack

I would like to define a class which inherits from a bunch of classes but which does not hide some specific methods from those classes.
Imagine the following code:
template<typename... Bases>
class SomeClass : public Bases...
{
public:
using Bases::DoSomething...;
void DoSomething(){
//this is just another overload
}
};
The problem is now if just one class does not have a member with the name DoSomething I get an error.
What I already tried was emulating an "ignore-if-not-defined-using" with a macro and SFINAE but to handle all cases this becomes very big and ugly!
Do you have any idea to solve this?
It would be really nice if I could define: "Hey using - ignore missing members".
Here I have some sample code: Godbolt
The problem with Jarod42's approach is that you change what overload resolution looks like - once you make everything a template, then everything is an exact match and you can no longer differentiate between multiple viable candidates:
struct A { void DoSomething(int); };
struct B { void DoSomething(double); };
SomeClass<A, B>().DoSomething(42); // error ambiguous
The only way to preserve overload resolution is to use inheritance.
The key there is to finish what ecatmur started. But what does HasDoSomething look like? The approach in the link only works if there is a single, non-overloaded, non-template. But we can do better. We can use the same mechanism to detect if DoSomething exists that is the one that requires the using to begin with: names from different scopes don't overload.
So, we introduce a new base class which has a DoSomething that will never be for real chosen - and we do that by making our own explicit tag type that we're the only ones that will ever construct. For lack of a better name, I'll name it after my dog, who is a Westie:
struct westie_tag { explicit westie_tag() = default; };
inline constexpr westie_tag westie{};
template <typename T> struct Fallback { void DoSomething(westie_tag, ...); };
And make it variadic for good measure, just to make it least. But doesn't really matter. Now, if we introduce a new type, like:
template <typename T> struct Hybrid : Fallback<T>, T { };
Then we can invoke DoSomething() on the hybrid precisely when T does not have a DoSomething overload - of any kind. That's:
template <typename T, typename=void>
struct HasDoSomething : std::true_type { };
template <typename T>
struct HasDoSomething<T, std::void_t<decltype(std::declval<Hybrid<T>>().DoSomething(westie))>>
: std::false_type
{ };
Note that usually in these traits, the primary is false and the specialization is true - that's reversed here. The key difference between this answer and ecatmur's is that the fallback's overload must still be invocable somehow - and use that ability to check it - it's just that it's not going to be actually invocable for any type the user will actually use.
Checking this way allows us to correctly detect that:
struct C {
void DoSomething(int);
void DoSomething(int, int);
};
does indeed satisfy HasDoSomething.
And then we use the same method that ecatmur showed:
template <typename T>
using pick_base = std::conditional_t<
HasDoSomething<T>::value,
T,
Fallback<T>>;
template<typename... Bases>
class SomeClass : public Fallback<Bases>..., public Bases...
{
public:
using pick_base<Bases>::DoSomething...;
void DoSomething();
};
And this works regardless of what all the Bases's DoSomething overloads look like, and correctly performs overload resolution in the first case I mentioned.
Demo
How about conditionally using a fallback?
Create non-callable implementations of each method:
template<class>
struct Fallback {
template<class..., class> void DoSomething();
};
Inherit from Fallback once for each base class:
class SomeClass : private Fallback<Bases>..., public Bases...
Then pull in each method conditionally either from the base class or its respective fallback:
using std::conditional_t<HasDoSomething<Bases>::value, Bases, Fallback<Bases>>::DoSomething...;
Example.
You might add wrapper which handles basic cases by forwarding instead of using:
template <typename T>
struct Wrapper : T
{
template <typename ... Ts, typename Base = T>
auto DoSomething(Ts&&... args) const
-> decltype(Base::DoSomething(std::forward<Ts>(args)...))
{
return Base::DoSomething(std::forward<Ts>(args)...);
}
template <typename ... Ts, typename Base = T>
auto DoSomething(Ts&&... args)
-> decltype(Base::DoSomething(std::forward<Ts>(args)...))
{
return Base::DoSomething(std::forward<Ts>(args)...);
}
// You might fix missing noexcept specification
// You might add missing combination volatile/reference/C-elipsis version.
// And also special template versions with non deducible template parameter...
};
template <typename... Bases>
class SomeClass : public Wrapper<Bases>...
{
public:
using Wrapper<Bases>::DoSomething...; // All wrappers have those methods,
// even if SFINAEd
void DoSomething(){ /*..*/ }
};
Demo
As Barry noted, there are other drawbacks as overload resolution has changed, making some call ambiguous...
Note: I proposed that solution as I didn't know how to create a correct traits to detect DoSomething presence in all cases (overloads are mainly the problem).
Barry solved that, so you have better alternative.
You can implement this without extra base classes so long as you’re willing to use an alias template to name your class. The trick is to separate the template arguments into two packs based on a predicate:
#include<type_traits>
template<class,class> struct cons; // not defined
template<class ...TT> struct pack; // not defined
namespace detail {
template<template<class> class,class,class,class>
struct sift;
template<template<class> class P,class ...TT,class ...FF>
struct sift<P,pack<>,pack<TT...>,pack<FF...>>
{using type=cons<pack<TT...>,pack<FF...>>;};
template<template<class> class P,class I,class ...II,
class ...TT,class ...FF>
struct sift<P,pack<I,II...>,pack<TT...>,pack<FF...>> :
sift<P,pack<II...>,
std::conditional_t<P<I>::value,pack<TT...,I>,pack<TT...>>,
std::conditional_t<P<I>::value,pack<FF...>,pack<FF...,I>>> {};
template<class,class=void> struct has_something : std::false_type {};
template<class T>
struct has_something<T,decltype(void(&T::DoSomething))> :
std::true_type {};
}
template<template<class> class P,class ...TT>
using sift_t=typename detail::sift<P,pack<TT...>,pack<>,pack<>>::type;
Then decompose the result and inherit from the individual classes:
template<class> struct C;
template<class ...MM,class ...OO> // have Method, Others
struct C<cons<pack<MM...>,pack<OO...>>> : MM...,OO... {
using MM::DoSomething...;
void DoSomething();
};
template<class T> using has_something=detail::has_something<T>;
template<class ...TT> using C_for=C<sift_t<has_something,TT...>>;
Note that the has_something here supports only non-overloaded methods (per base class) for simplicity; see Barry’s answer for the generalization of that.

Factory method for template classes

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?

Using Type Traits from Base Class

I am trying to understand the concept of type traits.
Say i have some templatized Class Hierachy like this and a client function:
template<typename T>
class Base
{
public:
//...
virtual bool inline isSymmetric() const = 0;
};
template<typename T>
class ChildrenOperation : public Base<T>
{
public:
//...
virtual bool inline isSymmetric() const override
{
return true;
}
};
template<typename T>
void clientFunction(const Base<T>& operation)
{
//...
if(operation.isSymmetric())
{
// use operation in one way
} else {
// use operation in another way
}
}
Obviously, clientFunction is polymorphic and different children can have different implementations of isSymmetric.
However, since isSymmetric seems to be constant and really more of a type information, i've read about type traits and i was wondering whether it is possible to rewrite the client function to not depend on isSymmetric on runtime, but rather compile time.
I've tried adding a trait like this. But i am not sure how to specialize it and use it in a polymorphic context.
template <typename T>
struct is_symmetric {
static const bool value = false;
};
If being symmetric depends on the concrete type derived from Base, then you cannot use a type traits for this situation. Type traits are evaluated in compile time, so if you have a polymorphic type which's traits are not known at compile time, then you cannot use type traits.
One possible solution, if the symmetricity is really constant, is this:
class Base {
public:
Base(bool symmetric) : symmetric(symmetric) {}
bool isSymmetric() {
return symmetric;
}
// ...
private:
bool symmetric;
};
class ChildrenOperation : public Base {
public:
ChildrenOperation() : Base(true) {}
// ...
};
I did not use the templates here because they are irrelevant in this case. Of course, if symmetricity depends on T then you can use type traits, like this:
template <typename T>
struct is_symmetric : public std::false_type {};
template <>
struct is_symmetric<SymmetricT> : public std::true_type {};
So the solution depends on whether the trait depends only on the dynamic type of the object, in which case you should use the fist code, the template parameter, in which case you should use the second code, or both. From your example, it's not entirely clear which is your situation.

Base class template member function shadowed in Derived class, albeit different parameter list

This has me wondering. Suppose I have :
class Base
{
public:
template<typename T>
void foo(T& varT)
{
//
}
template<typename T, typename U>
void foo(T& varT, U& varU)
{
//
}
};
class Child : public Base
{
public:
template<typename T, typename U, typename Z>
void foo(T& varT, U& varU, Z& varZ)
{
//
}
};
Now when I try this:
Child c;
char cVar;
int iVar;
float fVar;
c.foo(cVar);
c.foo<int>(cVar);
c.template foo<int>(cVar);
None of the calls work. They are always shadowed with error 'No matching member function for call'. Can anybody point me to a way to resolve this? I read in the standard that derived objects shadow template functions inherited but the standard explicitly said that the parameter list must be the same if they are shadowed.
Appreciate the help.
Hiding base members always happens when you have a name in a derived class that is present in a base class. The basic reason is that it is desirable to guard derived class uses against changes in the base class: assuming names from bases were not hidden, if a new overload in a base class is added a working look-up to a derived member may be hijacked to rather refer to the base class without any indication in the derived class that something may happen in the base class. If you mean to make the base members available, you can use a using declaration:
class Child : public Base
{
public:
using Base::foo; // declare that you want look up members from the base class
template<typename T, typename U, typename Z>
void foo(T& varT, U& varU, Z& varZ)
{
//
}
};
In your code you had three calls:
c.foo(cVar) works with the using declaration.
c.foo<int>(cVar) doesn't work even with the using declaration because you can't bind a non-const reference to int to a char lvalue. Using c.foo<char>(cVar) would work.
c.template foo<int>(cVar) suffers from the same problem. Since c is clearly not a dependent name, there is no need at all to use template in this context.
Without the using declaration you can call the member by qualifying the call explicitly, e.g.:
c.Base::foo(cVar);
You need this:
http://en.cppreference.com/w/cpp/language/using_declaration
Add to Child's definition:
using Base::foo;