这个答案重点在于这个问题;
给定一个类型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>());
}
See the demo here。
如果我们删除constexpr
,我们也可以删除check_base_
函数的不需要的行内定义。
注:溶液假定/断言可访问的基类(即,不是private
或protected
)。如果基类为private
,则上面的代码将无法编译,并具有可访问性错误。下面的代码不会失败,SFINAE是为了让编译继续。
Online demo here。
#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...");
}
的可能的复制[性状,以检查是否模板类的一些专业化是基类特定类的](http://stackoverflow.com/questions/25845536/trait-to-check-if-some-specialization -of-template-class-is-base-class-of-specifi) – Orient
如果你是作者,如果'c',你可以让你的生活更容易,如果你从非模板基类'类派生'c' foo {}'然后检查'F'是否使用普通的'std :: is_base_of'从'foo'派生。 –
@ JohannesSchaub-litb是的,我知道,同时我决定使用这样一个'e_tag'类。 – 0xbadf00d