gpt4 book ai didi

c++ - 使用SFINAE分辨率区分普通模板参数和模板模板参数的技术

转载 作者:太空狗 更新时间:2023-10-29 20:58:59 25 4
gpt4 key购买 nike

受最近出现的问题启发question about extended std::is_base_of type trait .

有没有什么技术可以让我们区分现代 C++ 或其扩展(例如,-std=gnu++1z)中的普通模板参数和模板模板参数> clang++/g++)?

namespace details
{

template< /* ??? */ base >
struct is_derived_from;

template< typaneme base >
struct is_derived_from< base >
{
static std::true_type test(base *);
static std::false_type test(void *);
};

template< template< typename ...formal > base >
struct is_derived_from< /* ??? */ >
{
template< typename ...actual > // actual parameters must be here!
static std::true_type test(base< actual... > *);
static std::false_type test(void *);
};

} // namespace details

template< typename derived, /* ??? */ base >
using is_derived_from = decltype(details::is_derived_from< /* ? base< ? > */ >::test(std::declval< typename std::remove_cv< derived >::type * >()));

在积极的情况下,它允许我们使一些有用的类型特征更加强大(例如,STL 的 std::is_base_of)。

我认为它需要一种语言特性作为“通用类型名称”,不是吗?

最佳答案

类模板只能有一组模板参数,但您可以使用重载 constexpr 函数模板来代替分派(dispatch)到适当的类模板。采用 linked question 中的 is_derived_from 特征,带有一个额外的 SFINAE 参数,这样当 B 是不可访问或不明确的基数时,您就不会遇到硬错误:

#include <type_traits>
namespace detail
{
template <template <class...> class B, typename Derived>
struct is_derived_from
{
using U = typename std::remove_cv<Derived>::type;

template <typename... Args,
typename = std::enable_if_t<
std::is_convertible<U*, Base<Args...>*>::value>>
static auto test(B<Args...>*)
-> typename std::integral_constant<bool
, !std::is_same<U, B<Args...>>::value>;

static std::false_type test(void*);

using type = decltype(test(std::declval<U*>()));
};

using std::is_base_of; // may want to use is_convertible instead to match
// the semantics of is_derived_from
}

template <template <class...> class B, typename Derived>
constexpr bool my_is_base_of() { return detail::is_derived_from<B, Derived>::type::value; }

template <class B, typename Derived>
constexpr bool my_is_base_of() { return detail::is_base_of<B,Derived>::value; }

struct B {};
struct D : B {};

template<class ...>
struct B2 {};
struct D2 : B2<int, double> { };

int main() {
static_assert(my_is_base_of<B2, D2>(), "Oops");
static_assert(my_is_base_of<B, D>(), "Oops");
static_assert(my_is_base_of<B2<int, double>, D2>(), "Oops");
static_assert(!my_is_base_of<B, D2>(), "Oops");
}

Demo .

关于c++ - 使用SFINAE分辨率区分普通模板参数和模板模板参数的技术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25881668/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com