Think of a type P
that should be thought of as templated by some type T
. However, P
wraps some perl library, and the type T
is only known at run time. On the C++ side, I can ask a P
for its type. There are only finitely many choices. I have a function f
that should be templated by T
. Because of this perl-library thing, I have to dispatch on f
's template dynamically. Because I have several functions like f
, I want to solve this as generically as possible. At the moment, I have
template<typename Fun, typename... Args>
P dispatch(Fun fun, P p, Args&&... args){
if(p.hasmembertype("T1"))
return fun.template operator()<T1>(p, std::forward<Args>(args)...);
if(p.hasmembertype("T2"))
return fun.template operator()<T2>(p, std::forward<Args>(args)...);
...
else
throw std::runtime_error("Unsupported type.");
}
This leaves me with the problem that every time I want to use this, I have to wrap a concrete f
in a functor:
struct {
template<typename T>
P operator()(P& p) {
return f<T>(p);
}
} static const f_wrapper;
...
dispatch(f_wrapper, p, ...);
Can this be solved more elegantly? I am bound to C++17; however, I'd be also interested if there exists an elegant solition in a more recent C++ standard.
Edit: To clarify, it is not the case that P
is a T1
, T2
etc., but P
has some member type T
that I can ask for with hasmembertype
.
Think of a type P
that should be thought of as templated by some type T
. However, P
wraps some perl library, and the type T
is only known at run time. On the C++ side, I can ask a P
for its type. There are only finitely many choices. I have a function f
that should be templated by T
. Because of this perl-library thing, I have to dispatch on f
's template dynamically. Because I have several functions like f
, I want to solve this as generically as possible. At the moment, I have
template<typename Fun, typename... Args>
P dispatch(Fun fun, P p, Args&&... args){
if(p.hasmembertype("T1"))
return fun.template operator()<T1>(p, std::forward<Args>(args)...);
if(p.hasmembertype("T2"))
return fun.template operator()<T2>(p, std::forward<Args>(args)...);
...
else
throw std::runtime_error("Unsupported type.");
}
This leaves me with the problem that every time I want to use this, I have to wrap a concrete f
in a functor:
struct {
template<typename T>
P operator()(P& p) {
return f<T>(p);
}
} static const f_wrapper;
...
dispatch(f_wrapper, p, ...);
Can this be solved more elegantly? I am bound to C++17; however, I'd be also interested if there exists an elegant solition in a more recent C++ standard.
Edit: To clarify, it is not the case that P
is a T1
, T2
etc., but P
has some member type T
that I can ask for with hasmembertype
.
2 Answers
Reset to default 3The solution here is to define a single non-template function with signature std::variant<T1, T2, T3> get_member(P const&)
.
You can then call std::visit( [](auto&& p){polarize(p);}, get_member(p) );
The get_member
code will need the logic to extract the Perl member data, using that p.hasmembertype("T1")
logic from the question.
Rather than wrap every function, you can wrap P
once.
template <typename T>
struct WrappedP {
P value;
using type = T;
};
template <typename... Ts>
struct VariantP {
VariantP(P) { /* existing dispatch to populate variant */ }
std::variant<WrappedP<Ts>...> variant;
};
Then for each template, you can
std::visit([]<typename T>(WrappedP<T>& wrapper){ f<T>(wrapper.value); }, variant);
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744207598a4563178.html
std::variant<T1, T2, T3>
. We do not need to know that this variant originated in Perl - the answer would be the same if that variant came from Python. What is important is that setT1,T2,T3
. It has to be finite and enumerable. A runtime error is literally impossible then. (Of course, you could have a runtime error reading data from perl.) – MSalters Commented Mar 25 at 9:14T
is a member type of some Perl structure; see my edit, please. – Bubaya Commented Mar 25 at 9:16P
tostd::variant<T1,T2,T3>
so that you can then callstd::visit([](auto&& p) { polarize(p); }, myVar );
– MSalters Commented Mar 25 at 9:23p
has some member that's hidden from me. I can ask for the type of that member by string, but I cannot access it in the sense of a C++ member. The type ofp
isP
in all cases, andf
is templated not on the type ofp
, but on the type of something insidep
. If I misunderstand you, I am deeply sorry. Please post an answer or elaborate in that case. – Bubaya Commented Mar 25 at 9:30T1
/T2
directly, it seems you are limited to use the function from the library (polarize<T>
), whereas you cannot havemy_func<T>
. – Jarod42 Commented Mar 25 at 10:02