I have a std::variants containing objects with different interfaces. Goal is to call some of the methods if the object in variant has it. I'm trying to make a couple of template decorators and looking for a way to do it with less boilerplate and without macro. Finally my idea looks like:
class Good
{
public:
void a(int);
float b(float);
int c(double);
};
class Bad
{
public:
void a(int);
int c(double);
};
template<class T>
class View : protected T
{
public:
using T::a;
using T::b;
};
template<class T, template<class> class V>
constexpr bool IsFitToView = // ??
//usage
std::variant<Good, Bad> variant = //;
std::visit([](auto&& obj) {
if constexpr(IsFitToView<std::decay_t<decltype(obj)>, View>)
{
View view{obj}; // create view from obj
//here work with obj as view, calling a `a` and `b` methods;
}
}, variant);
Main problem is how to create IsFitToView check. My approach is:
template<class T, template<class> class V, class = void>
struct IsFit : std::false_type
{};
template<class T, template<class> class V>
struct IsFit<T, V, std::void_t<V<T>>> : std::true_type
{};
template<class T, template<class> class V>
constexpr bool IsFitToView = IsFit<T, V>::value;
I had a hope that it has to work like SFINAE does: View<Good>
compiles and template specialization selected, View<Bad>
cannot be compiled because of using T::b;
in a View
.
But it returns true both for Good and Bad types!
std::cout << IsFitToView<Good, View> << IsFitToView<Bad, View>;
I know I can check the methods existence by a checking it indvidualy and check it like
if constexpr(HasAFunc<T> && HasBFunc<T> && ...
But I have to create many different Views
. It is very verbose and hard to read.
Please, could you explain why my approach doesn't work and give any ideas to do what I want.
Thanks!