【发布时间】:2020-06-03 17:02:56
【问题描述】:
我有一个 std::variants 包含具有不同接口的对象。目标是如果变体中的对象具有某些方法,则调用它。 我正在尝试制作几个模板装饰器,并寻找一种方法来使用更少的样板和没有宏。 最后我的想法是这样的:
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);
主要问题是如何创建 IsFitToView 检查。我的做法是:
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;
我希望它必须像 SFINAE 那样工作:View<Good> 编译并选择模板专业化,View<Bad> 无法编译,因为 using T::b; 在 View 中。
但它对 Good 和 Bad 类型都返回 true!
std::cout << IsFitToView<Good, View> << IsFitToView<Bad, View>;
我知道我可以通过单独检查来检查方法是否存在,并像这样检查
if constexpr(HasAFunc<T> && HasBFunc<T> && ...
但我必须创建许多不同的Views。它非常冗长且难以阅读。
请你解释一下为什么我的方法不起作用并给出任何想法来做我想做的事。
谢谢!
【问题讨论】:
-
View正文,包括using T::a;,在IsFit的直接上下文之外。 -
或许可以定义a concept for each view?
-
听起来您是在尝试重塑
std::is_convertable或在较小程度上重塑std::is_invocable?
标签: c++ templates c++17 sfinae