请考虑以下代码段:
template<class A, class B>
class c {};
template<class D>
class e
: public c<e<D>, /* some type depending on D */>
{ }
如果类型为F
,我该如何检查某些类型B
是否F
来自c<F, B>
?
示例:对于F = e<D>
,某些类型B
取决于D
,F
来自c<F, B>
。
答案 0 :(得分:3)
这个答案集中在这个问题上;
如果类型为
F
,我该如何检查某些类型B
是否F
来自c<F, B>
?
澄清的评论;
该特征应该检查某些
F
c<F, B>
是否来自B
(而B
是什么并不重要。)
可以使用两个constexpr
函数来“吸引”并将基础c<F, B>
与其他类型区分开来。 功能模板受到青睐,因为它们能够deduce types (这需要满足某些B
的要求)。形式如下......
template <typename F, typename B>
constexpr bool check_base(C<F, B> &&) { return true; }
template <typename F>
constexpr bool check_base(...) { return false; }
以下示例(使用改进的使用方案)说明了基本工作原理;
#include <utility>
template <typename A, typename B>
struct C {};
template <typename F, typename B>
constexpr std::true_type check_base_(C<F, B>&&) { return {}; }
template <typename F>
constexpr std::false_type check_base_(...) { return {}; }
template <typename T>
using check_base = decltype(check_base_<T>(std::declval<T>()));
template <typename D>
struct E : C<E<D>, D> {};
struct FailF {};
int main()
{
static_assert(check_base<E<int>>());
static_assert(!check_base<FailF>());
}
如果我们删除了constexpr
,我们也可以删除check_base_
函数中不需要的内联定义。
注意:解决方案假定/断言可访问的基类(即不是private
或protected
)。如果基类是private
,则上面的代码将无法编译,并且存在可访问性错误。下面的代码不会失败,完成SFINAE以允许继续编译。
#include <utility>
#include <type_traits>
template <typename A, typename B>
struct C {};
template <typename F, typename B>
std::true_type check_base_(C<F, B>&&, typename std::enable_if<std::is_convertible<F, C<F,B>>::value>::type* = nullptr);
template <typename F>
std::false_type check_base_(...);
template <typename T>
using check_base = decltype(check_base_<T>(std::declval<T>()));
template <typename D>
struct Example : C<Example<D>, D> {};
struct CtorTest : C<CtorTest, int> { CtorTest(int, int) {} };
struct PrivateBase : private C<PrivateBase, double> {};
struct FailTest {};
int main()
{
static_assert(check_base<Example<int>>(), "fail...");
static_assert(check_base<CtorTest>::value, "fail...");
static_assert(!check_base<PrivateBase>(), "fail...");
static_assert(!check_base<FailTest>(), "fail...");
}