std::map with function pointers - c++

My issue here is not that I can't map to function pointers, but more the other way around.
With my current setup, I can instantiate classes through strings.
Now, I'm trying to get strings from class types.
My proposed method:
class A {};
template <typename T> T* create(void) { return new T; }
static std::map<std::string,A*(*)(void)> str_to_class;
static std::map<A*(*)(void),std::string> class_to_str;
template <typename T> void Bind(std::string identity) {
// T must inherit from A.
str_to_class[identity]=&create<T>;
class_to_str[&create<T>]=identity;
}
A* MakeFromString(std::string identity) {
return str_to_class[identity](); // Compiles fine.
}
template <typename T> std::string GetTypeString(void) {
return class_to_str[&create<T>]; // Error!
}
int main(int,char**) {
Bind<A>("A");
A* new_entity=CreateFromString("A");
}
Error: C2679: binary '[' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
I know I can use dynamic_cast<> to check entity types, but that would require writing code for every class that would be used.

The problem is that create() returns a type different than what is specified as the return type of the maps key template argument. Since everything uses A as the base / primary class type you should consider doing the same for create().
template <typename T> A* create(void) { return new T; }
^^^^

I have done something similar which is about mapping string to function pointer of any type. From my answer which was posted here:
#include <string>
#include <iostream>
#include <map>
#include <vector>
int fun1(){
std::cout<<"inside fun1\n";
return 2;
}
void fun2(void){
std::cout<<"inside fun2\n";
}
int fun3(int a){
std::cout<<"inside fun3\n";
return a;
}
std::vector<int> fun4(){
std::cout<<"inside fun4\n";
std::vector<int> v(4,100);
return v;
}
// every function pointer will be stored as this type
typedef void (*voidFunctionType)(void);
struct Interface{
std::map<std::string,voidFunctionType> m1;
template<typename T>
void insert(std::string s1, T f1){
m1.insert(std::make_pair(s1,(voidFunctionType)f1));
}
template<typename T,typename... Args>
T searchAndCall(std::string s1, Args&&... args){
auto mapIter = m1.find(s1);
/*chk if not end*/
auto mapVal = mapIter->second;
// auto typeCastedFun = reinterpret_cast<T(*)(Args ...)>(mapVal);
auto typeCastedFun = (T(*)(Args ...))(mapVal);
return typeCastedFun(std::forward<Args>(args)...);
}
};
int main(){
Interface a1;
a1.insert("fun1",fun1);
a1.insert("fun2",fun2);
a1.insert("fun3",fun3);
a1.insert("fun4",fun4);
int retVal = a1.searchAndCall<int>("fun3",2);
a1.searchAndCall<void>("fun2");
auto temp = a1.searchAndCall<std::vector<int>>("fun4");
return 0;
}

Related

C++ O(1) lookup by derived type

I have a vector of pointers to Base.
Invariant: only one of each derived type should be in that vector at any time.
I also want to be able to lookup the value with a given type in O(1). I can do this in O(n) easily, by checking dynamic_cast.
Basically, I want to replace my vector with a map or something. Is that possible?
Here's minimal example with the vector and the loop:
#include <functional>
#include <iostream>
#include <memory>
#include <type_traits>
#include <vector>
using namespace std;
typedef struct Base {
virtual ~Base(){};
} Base;
vector<unique_ptr<Base>> baseList;
template <typename NarrowType,
typename std::enable_if_t<
! std::is_same_v<Base, NarrowType> &&
std::is_base_of_v<Base, NarrowType>,
bool> = true>
void ApplyFuncToType(function<void(NarrowType)> func) {
// Want to get rid of this loop
for (auto &base : baseList) {
NarrowType *narrow = dynamic_cast<NarrowType *>(base.get());
if (narrow) {
func(*narrow);
}
}
}
// usage
int main() {
typedef struct A : Base {
void printA() { cout << "a" << endl; }
} A;
typedef struct B : Base {
void printB() { cout << "b" << endl; }
} B;
baseList.push_back(make_unique<A>());
baseList.push_back(make_unique<B>());
ApplyFuncToType<A>([](A a) { a.printA(); });
}
Questions:
How can I enfore my invariant (one of each type max in container)
Would a unordered_map<type_info, unique_ptr<Base>> be a good solution to this? I have read that typeid is not consistent or safe to use or something, but am not sure exactly.
Edits/Clarification:
This is for a system where other classes can register their own types in this vector. i.e. the contents of the vector will change during runtime.
A similar approach is shown here, where an unordered_map is used to allow self-registered event callbacks.
Yeah, sure, it's possible, but I'm not convinced you need it. After all, all your types are completely static.
Also, ApplyFuncToType shouldn't be taking std::function, but a generic argument, since you'll save on the cost of shoehorning things into std::function. You're not deducing any types anyway - because std::function is not a tool for that - and thus you have the call that includes the type parameter explicitly: ApplyFuncToType<A>.
And finally, it's probably wrong to pass A and B to the lambda by value - since then the instance the lambda is using is not the instance you so carefully deposited beforehand (!). It should be passed by const reference, or by reference if it's a non-const method:
// Do this
ApplyFuncToType<A>([](const A &a) { a.printA(); });
// Or do that
ApplyFuncToType<A>([](A &a) { a.printA(); });
// NO!
ApplyFuncToType<A>([](A a) { a.printA(); });
It's hard to deduce it ahead of time, but I imagine that you'd want to make A, B, ... non-copyable but they definitely should be movable (read on).
A Tuple of Pointers
All you really want is the below - and it doesn't care that the types are derived from some base, you can use any types you wish. You can of course add type constraints if you want to protect from bugs where wrong types are supplied to ptr_tuple.
#include <functional>
#include <memory>
#include <tuple>
struct A { void methodA() {} };
struct B { void methodB() {} };
template <class ...Args>
using ptr_tuple = std::tuple<std::unique_ptr<Args>...>;
ptr_tuple<A, B> instances;
template <typename T>
auto &instance()
{
return std::get<std::unique_ptr<T>>(instances);
}
template <class T, class Fun, class ...Args>
void invoke(Fun &&fun, Args &&...args)
{
auto *ptr = instance<T>().get();
if (ptr) {
std::invoke(fun, *ptr, std::forward<Args>(args)...);
}
}
int main() {
instance<A>() = std::make_unique<A>();
instance<B>() = std::make_unique<B>();
invoke<A>([](A& a){ a.methodA(); });
invoke<B>([](B& b){ b.methodB(); });
}
Argument Deduction for Invoke/Apply
It's not even necessary to supply the explicit type parameter to invoke. We can deduce it. For that, we use a traits class that's sorely missing in C++ standard library:
// from https://stackoverflow.com/a/39717241/1329652
// see also
// https://github.com/kennytm/utils/blob/master/traits.hpp
// https://stackoverflow.com/a/27885283/1329652
// boost::callable_traits
template <typename T, typename = void>
struct function_traits;
template <typename R, typename... A>
struct function_traits<R (*)(A...)>
{
using args_type = std::tuple<A... >;
using arg0_class = std::decay_t<std::tuple_element_t<0, args_type>>;
};
template <typename R, typename C, typename... A>
struct function_traits<R (C::*)(A...)>
{
using args_type = std::tuple<A... >;
using arg0_class = std::decay_t<std::tuple_element_t<0, args_type>>;
};
template <typename R, typename C, typename... A>
struct function_traits<R (C::*)(A...) const>
{
using args_type = std::tuple<A... >;
using arg0_class = std::decay_t<std::tuple_element_t<0, args_type>>;
};
template <typename T>
struct function_traits<T, std::void_t<decltype(&T::operator())> >
: public function_traits< decltype(&T::operator()) >
{};
And then we can deduce the needed type in invoke:
template <class Fun, class ...Args>
void invoke(Fun &&fun, Args &&...args)
{
using arg0_class = typename function_traits<std::decay_t<Fun>>::arg0_class;
auto *ptr = instance<arg0_class>().get();
if (ptr) {
std::invoke(fun, *ptr, std::forward<Args>(args)...);
}
}
int main() {
instance<A>() = std::make_unique<A>();
instance<B>() = std::make_unique<B>();
invoke([](A& a){ a.methodA(); });
invoke([](B& b){ b.methodB(); });
}
A Tuple of Optional Values
Depending on what your A and B types really are, if they can be moved, then using dynamic memory allocation is totally unnecessary, you'd much rather keep them by value, e.g. with optional:
#include <functional>
#include <memory>
#include <optional>
#include <tuple>
struct A { void methodA() {} };
struct B { void methodB() {} };
template <class ...Args>
using opt_tuple = std::tuple<std::optional<Args>...>;
opt_tuple<A, B> instances;
template <typename T> auto &instance()
{
return std::get<std::optional<T>>(instances);
}
template <class T, class Fun, class ...Args>
void invoke(Fun &&fun, Args &&...args)
{
auto &opt = instance<T>();
if (opt) {
std::invoke(fun, *opt, std::forward<Args>(args)...);
}
}
int main() {
instance<A>().emplace(); // constructs A
instance<B>().emplace(); // constructs B
invoke<A>([](A& a){ a.methodA(); });
invoke<B>([](B& b){ b.methodB(); });
}
Of course you can add the type-deduced variant of invoke just as before.
A type-id Stand In
Even though I really think that your original solution is in want of a problem - you should state what problem you're trying to solve, otherwise it smells of an XY problem - there of course is a better "type id" than type_id: an address of a function templated on a type. There'll be only one instance of it per program.
I don't think that the "O(1)" lookup is a real requirement, a very, very fast O(log(N)) lookup - way faster than you'd get from e.g. std::map, will work just as well for whatever your imaginary applications is.
Thus:
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <type_traits>
#include <vector>
// here goes function_traits implementation from above
struct Base {};
template <typename T>
constexpr static bool is_derived_from_Base_v =
!std::is_same_v<Base, T> && std::is_base_of_v<Base, T>;
class UniqueTypeObjects {
using marker_type = void(*)();
struct Pair {
std::unique_ptr<Base> base;
marker_type marker;
Pair(std::unique_ptr<Base> &&base, marker_type marker) : base(std::move(base)), marker(marker) {}
bool operator<(marker_type o) const { return marker < o; }
};
friend bool operator<(marker_type a, const Pair &o);
template <typename T, typename = std::enable_if<is_derived_from_Base_v<T>>>
struct Witness {
static void marker() {}
};
std::vector<Pair> m_objects;
public:
template <class Derived, class =
std::enable_if_t<is_derived_from_Base_v<Derived>>>
void insert(std::unique_ptr<Derived> &&obj) {
auto constexpr marker = &Witness<Derived>::marker;
auto it = std::lower_bound(m_objects.begin(), m_objects.end(), marker);
if (it != m_objects.end() && it->marker == marker)
throw std::logic_error("Attempting to insert an object of duplicate type");
m_objects.emplace(it, std::move(obj), marker);
}
template <typename Derived, typename Fun,
class = std::enable_if_t<is_derived_from_Base_v<Derived>>>
void apply(Fun fun) const {
auto constexpr marker = &Witness<Derived>::marker;
auto it = std::lower_bound(m_objects.begin(), m_objects.end(), marker);
if (it == m_objects.end() || it->marker != marker)
throw std::runtime_error("No object found to apply the function to");
std::invoke(fun, *static_cast<Derived*>(it->base.get()));
}
template <typename Fun,
class = std::enable_if_t<is_derived_from_Base_v<
typename function_traits<std::decay_t<Fun>>::arg0_class>>>
void apply(Fun fun) const {
using arg0_class = typename function_traits<std::decay_t<Fun>>::arg0_class;
apply<arg0_class>(std::move(fun));
}
};
bool operator<(void(*a)(), const UniqueTypeObjects::Pair &o)
{ return a < o.marker; }
char lastInvoked;
int main() {
struct A : Base {
void methodA() { lastInvoked = 'A'; }
};
struct B : Base {
void methodB() { lastInvoked = 'B'; }
};
UniqueTypeObjects uto;
uto.insert(std::make_unique<A>());
uto.insert(std::make_unique<B>());
assert(!lastInvoked);
uto.apply([](A &a){ a.methodA(); });
assert(lastInvoked == 'A');
uto.apply([](B &b){ b.methodB(); });
assert(lastInvoked == 'B');
}
But I still don't think it's necessary. If you truly have O(1) requirement, e.g. some sort of a realtime system, or system with deterministic execution timing, then the opt_tuple solution or its equivalent is the one you should use. Otherwise - good luck with the paperwork and test plans to ensure that UniqueTypeObjects works. I wrote the thing and even I wouldn't allow it in a realtime or hi-reliability codebase I maintained. Nothing beats static type safety and ensuring correctness by design, and you get that with the tuple approach (or its equivalent with a custom class).

dynamic_cast to derived type with unknown template argument

I would like to dynamic_cast to a templated derived type, with unknown template argument:
struct A {
virtual void f() { };
};
template <std::size_t N>
struct B : public A { };
With the known template argument the cast can be performed as:
const A& base_ref = B<N>();
const B<N>& ref = dynamic_cast<const B<N>&>(base_ref);
My question is about the case where the value of the template argument (N) is not known.
I was wondering if there is a way to obtain the object type, in this case B<N> from the base class pointer/reference, such that the dynamic_cast template parameter can be inferred automatically?
P.S. In the considered case the template argument is an integer type, and is used as a template parameter for an std::array.
If you have just a few possible values of N, then you can try dynamic_cast'ing to each of them. Otherwise, the answer is:
No. As a compile time constant, no. If you don't need a compile time constant, then you can do this:
struct AWithN {
int n;
AWithN(int n_) : n(n_) { }
};
template <std::size_t N>
struct B: public AWithN {
B() : AWithN(N) { }
};
And you can dynamic_cast to AWithN, from where you can get n.
OK, this is going to be nasty.
You can automate the lookup of a valid dynamic cast, if:
You cap the maximum value of N in B<N> to a value your compiler will be happy with.
You provide a visitor taking a template argument in order to action the result of a successful cast.
You don't mind sequential lookups (although further work here[1] would involve building a cache of successful lookups to improve runtime).
[1] further work would obviously be a waste of time. The time would be better spent working on a better design.
#include <type_traits>
#include <vector>
#include <iostream>
#include <utility>
#include <array>
#include <algorithm>
#include <stdexcept>
struct A
{
virtual ~A() = default;
};
template<std::size_t N>
struct B : A
{
};
template<std::size_t I>
struct cast_test
{
static bool test(A* p) {
return dynamic_cast<B<I>*>(p) != nullptr;
}
};
template<std::size_t...Is>
constexpr auto make_cast_tests(std::index_sequence<Is...>)
{
return std::array<bool(*)(A*), sizeof...(Is)> {
&cast_test<Is>::test...
};
}
template<class Visitor, std::size_t I>
struct caller
{
// figuring out a common return type is a whole new challenge...
static void call(Visitor& visitor, A* p) {
return visitor(static_cast<B<I>*>(p));
}
};
template<class Visitor, std::size_t...Is>
constexpr auto make_callers(std::index_sequence<Is...>)
{
return std::array<void(*)(Visitor&, A*), sizeof...(Is)> {
&caller<Visitor, Is>::call...
};
}
template<std::size_t N, class Visitor, class sequence_type = std::make_index_sequence<N>>
decltype(auto) dynamic_visit(Visitor&& visitor, A*p)
{
constexpr auto tests = make_cast_tests(sequence_type());
auto ipos = std::find_if(std::begin(tests), std::end(tests), [&p](auto&& f){ return f(p); });
if (ipos == std::end(tests))
{
throw std::logic_error("increase the range of N");
}
constexpr auto callers = make_callers<Visitor>(sequence_type());
auto icaller = std::begin(callers) + std::distance(std::begin(tests), ipos);
return (*icaller)(visitor, p);
}
struct visitor
{
template<std::size_t I>
void operator()(B<I>* p) const
{
std::cout << "I is " << I << std::endl;
}
};
auto make_an_A(int argc) -> A*
{
if (argc > 1) {
return new B<6>;
}
else {
return new B<7>;
}
}
int main(int argc, char** argv)
{
A* p = make_an_A(argc);
dynamic_visit<100>(visitor(), p);
}
expected result when invoked with ./a.out:
I is 7
expected result when invoked with ./a.out "foo":
I is 6

Passing a default value list to a template class

Not sure if this can be done using templates but I want to give it a try.
I have a template class which takes any struct, stores it and returns it. Additionally, I want an interface that resets the struct's data whenever requested.
#define MYDEFAULT {1,2,3}
template < typename ITEM, ITEM Default>
class myClass{
public:
myClass(ITEM item) : _item(item) {}
const ITEM* get(){
return &_item;
}
void reset(){
_item = Default;
}
ITEM _item;
};
// Set to default when instantiated
myClass<myStruct, MYDEFAULT> ABC(MYDEFAULT);
Of course that's not working at all, but what I want to achieve is the replacement of Default in reset(). I mean it would work if _item would be of type int.
How can this be realized?
EDIT: I want something like this:
template <typename Y, Y T>
class myclass {
public:
void reset() {
xxx = T;
}
Y xxx{10};
};
void test()
{
myclass<int, 5> _myclass;
}
Initially xxx is 10 and after invoking reset it is 5. This works, so it seems it is not possible for POD or class types?
EDIT2: It seems it is all about non-type template-arguments. https://stackoverflow.com/a/2183121/221226
So there is no way around traits when using structs.
As a viable solution, you can use a trait class as shown in the following working example:
#include<cassert>
struct S {
int i;
};
template<typename T>
struct Traits {
static constexpr auto def() { return T{}; }
};
template<>
struct Traits<S> {
static constexpr auto def() { return S{42}; }
};
template <typename ITEM>
class myClass {
public:
myClass(): _item(Traits<ITEM>::def()) {}
myClass(ITEM item): _item(item) {}
const ITEM* get() {
return &_item;
}
void reset() {
_item = Traits<ITEM>::def();
}
ITEM _item;
};
int main() {
myClass<S> ABC{};
myClass<int> is;
assert((ABC.get()->i == 42));
assert((*is.get() == 0));
}
The basic trait uses the default constructor of the type ITEM.
You can then specialize it whenever you want a different defaulted value for a specific class.
The same can be accomplished even with a factory function as:
template<typename T>
constexpr auto def() { return T{}; }
template<>
constexpr auto def<S>() { return S{42}; }
Anyway, traits can easily provide more types and functions all at once.
You can maybe simulate it using a data structure with a data member of type std::array.
A minimal, working example follows:
#include<cstddef>
#include<array>
#include<cassert>
template<typename T, T... I>
struct S {
S(): arr{ I... } {}
S(const T (&val)[sizeof...(I)]) {
for(std::size_t i = 0; i < sizeof...(I); ++i) {
arr[i] = val[i];
}
}
const T * get() {
return arr.data();
}
void reset() {
arr = { I... };
}
private:
std::array<T, sizeof...(I)> arr;
};
int main() {
S<int, 1, 3, 5> s{{ 0, 1, 2 }};
assert(s.get()[1] == 1);
s.reset();
assert(s.get()[1] == 3);
}
I'm not sure I got exactly what you are asking for, but the interface in the example is close to the one in the question and the implementation details should not affect the users of your class.

Accessing a member in a template: how to check if the template is a pointer or not?

Given the following declaration:
template<class T>
class A {
void run(T val) {
val.member ...
}
}
This code works fine if no pointers are used:
A<Type> a;
Type t;
a.run(t);
But using a pointer results in an error:
A<Type*> a;
Type* t = new Type();
a.run(t);
error: request for member ‘member’ which is of non-class type ‘T*’
Obviously in this case the member must be accessed via ->. What's the best way to handle this?
I found a solution on SO: Determine if Type is a pointer in a template function
template<typename T>
struct is_pointer { static const bool value = false; };
template<typename T>
struct is_pointer<T*> { static const bool value = true; };
...
if (is_pointer<T>::value) val->member
else val.member
But this is very verbose. Any better ideas?
You could use a simple pair of overloaded function templates:
template<typename T>
T& access(T& t) { return t; }
template<typename T>
T& access(T* t) { return *t; }
And then use them this way:
access(val).member = 42;
For instance:
template<typename T>
struct A
{
void do_it(T& val)
{
access(val).member = 42;
}
};
struct Type
{
int member = 0;
};
#include <iostream>
int main()
{
A<Type> a;
Type t;
a.do_it(t);
std::cout << t.member << std::endl;
A<Type*> a2;
Type* t2 = new Type(); // OK, I don't like this, but just to show
// it does what you want it to do...
a2.do_it(t2);
std::cout << t2->member;
delete t2; // ...but then, don't forget to clean up!
}
Here is a live example.
The best idea is probably to specialize your class for pointer types.
template<class T>
class A{ ...};
template<>
class A<T*> { //implement for pointers
};
If you feel that this is too verbose, you can use overload a get_ref function:
template<class T> T& get_ref(T & r) {return r;}
template<class T> T& get_ref(T* r) {return *r;}
template<class T>
class A {
void do(T val) {
get_ref(val).member ...
}
}

ambiguous template overload for template parameter is a container

Please consider the following example:
#include <string>
#include <vector>
using std::string;
using std::vector;
template <typename T>
const T GetValue()
{
return T(); // some value
}
template <typename T>
const vector<T> GetValue()
{
return vector<T>(); // some vector of values
}
int main(int argc, char* argv[])
{
int i = GetValue<int>();
vector<int> = GetValue<vector<int>>();
return 0;
}
I have two template functions which are supposed to parse values from some storage depending on an given type. The first should do the job for simple data types, the second for vectors of simple data types only.
My problem is that the template matching is ambiguous since T may be vector<T>.
I wonder how to implement the overload/specialization for the vector types properly.
Any help would be greatly appreciated!
One simple way is to use an out-param, so that the template parameter can be deduced from the argument:
#include <vector>
using std::vector;
template <typename T>
void GetValue(T &t)
{
t = T(); // some value
}
template <typename T>
void GetValue(vector<T> &v)
{
v = vector<T>(); // some vector of values
}
int main(int argc, char* argv[])
{
int i;
GetValue(i);
vector<int> v;
GetValue(v);
return 0;
}
GetValue(v) isn't ambiguous, since the template argument deduction rules say that the second overload is the better match.
This isn't necessarily the interface/style you want, though, in which case you could use partial specialization instead of overloading. But that requires a class, since function templates cannot be partially specialized:
#include <vector>
using std::vector;
template <typename T>
struct Getter {
T get(void) {
return T(); // some value
}
};
template <typename T>
struct Getter<vector<T> > {
vector<T> get(void) {
return vector<T>(); // some vector of values
}
};
template <typename T>
T GetValue(void)
{
return Getter<T>().get();
}
int main(int argc, char* argv[])
{
int i = GetValue<int>();
vector<int> v = GetValue<vector<int> >();
return 0;
}
Both version ofGetValue differs by only return type, hence it is not overload.
I would suggest you to have just one GetValue and then implement two functions which differ by parameter type, as opposed to return type, and forward the call as:
namespace details
{
template <typename T>
T FillValue(T*)
{
//your code
}
template <typename T>
vector<T> FillValue(vector<T> *)
{
//your code
}
}
template <typename T>
T GetValue()
{
return details::FillValue((T*)0); //pass null pointer of type T*
}
The correct FillValue will be selected by the compiler based on the type of the argument passed to the function, which is T*. If T is vector<U> for some type U, then the second function will be selected, otherwise the first function will be selected.
You can move the partial specialization to a helper class:
#include <vector>
template <typename T>
class Creator {
public:
T operator()() const { return T(); }
};
template <typename T>
class Creator<std::vector<T> > {
public:
std::vector<T> operator()() const { return std::vector<T>(); }
};
template <typename T>
T GetValue() {
return Creator<T>()();
}
int main() {
int i = GetValue<int>();
std::vector<char> v = GetValue<std::vector<char> >();
}
Put the general method inside a class (naming as GetValue preferably) and declare that method as operator T(). Now specialize the class for vector<T>:
template <typename T>
struct GetValue
{
operator const T () const
{
std::cout<<"GetValue()\n";
return T(); // some value
}
};
template <typename T>
struct GetValue<vector<T> >
{
operator const vector<T> ()
{
std::cout<<"GetValue<vector<T>>()\n";
return vector<T>(); // some vector of values
}
};
Usage:
int i = GetValue<int>();
vector<int> v = GetValue<vector<int> >();
Demo