Using C++ 17. I have the following:
template <typename T>
using ptr_t = std::shared_ptr<const T>;
class some_type;
class A { some_type foo() const; }
class B { some_type foo() const; }
class C { some_type foo(int) const; }
std::variant<ptr_t<A>, ptr_t<B>, ptr_t<C>>;
A variant holds shared_ptr(s) to different types. All expected to have function foo() that may be void or take a parameter. I will then have a visitor that would correctly dispatch foo, something like this (conceptually):
struct visitor
{
template <typename T>
ptr_t<some_type> operator()(const T& config) const
{
if constexpr (// determine if foo() of the underlying type of a shared_ptr can be called with int param)
return config->foo(15);
else
return config->foo();
}
is there a way to say this? I tried various ways but can't come with something that compiles. Template parameter, T, is ptr_t<A|B|C>.
std::is_invocable_v<Callable, Args...>is the way to go. Unfortunatelly, it will not compile just like that withif constexpr. It will either fail because "there is nooperator()()overload", or there is no overload for operator takingArgs....I suggest you add a wrapper class for a callable and use it with a specialized alias template of
std::variantinstead of writing your own visitor. It will allow you to usestd::visitseamlessly.https://godbolt.org/z/e6GzvW6n6
Take notice, that it does not depend on
if constexpr. So if you manage to provide your ownvariantandis_invocable_v, it will work for C++14. For C++11 possibly, but some modifications regardingconstexprfunctions might be needed.Of course you can implement your
visitorin the same manner if you want to usestd::shared_ptristead of a callable. But I don't see any reason to use:std::shared_ptr? Do you really need to share the ownership? Just stick withstd::unique_ptr