查找是不是可以使用一组参数实例化类模板,arity-wise(在 C++17 中)

Posted

技术标签:

【中文标题】查找是不是可以使用一组参数实例化类模板,arity-wise(在 C++17 中)【英文标题】:Finding if a class template can be instantiated with a set of arguments, arity-wise (in C++17)查找是否可以使用一组参数实例化类模板,arity-wise(在 C++17 中) 【发布时间】:2021-12-31 16:17:00 【问题描述】:

我有一个模板,它接受一个模板模板参数和一组类型参数。我只想在参数匹配时才用参数实例化模板。像这样的:

    // can_apply_t = ???

    template<template<typename...> typename Template, typename... Args>
    struct test 
        using type = std::conditional_t<can_apply_t<Template, Args...>, Template<Args...>, void>;
    ;


template<typename> struct unary_template;
template<typename, typename> struct binary_template;

static_assert(std::is_same_v< test<unary_template, int>::type, unary_template<int> >);
static_assert(std::is_same_v< test<binary_template, int>::type, void >);

我幻想它会像这样简单:

template<template<typename... T> typename Template, typename... Args>
struct test 
    using type = std::conditional_t<sizeof...(T) == sizeof...(Args), Template<Args...>, void>;    
;

...但是 clang++12 说:

错误:'T' 不是指参数包的名称

【问题讨论】:

sizeof...(T) 需要一组类型,而不是一组 class K,class V,...(不存在且无法推断)。 【参考方案1】:

幻想会这么简单:

不...没有那么简单...当你写作时

using type = std::conditional_t<can_apply_t<Template, Args...>,
                                Template<Args...>,
                                void>;

conditional_t 的测试为假时,Template&lt;Args...&gt; 也必须是可接受的类型。

你需要一个can_apply_t,在可能的情况下直接返回Template&lt;Args...&gt;,否则void

我建议如下

template <template <typename...> class C, typename... Ts>
auto can_apply_f (int)
  -> std::remove_reference_t<decltype(std::declval<C<Ts...>>())>;

template <template <typename...> class C, typename... Ts>
auto can_apply_f (long) -> void;

template <template <typename...> class C, typename ... Ts>
using can_apply_t = decltype(can_apply_f<C, Ts...>(0));

template <template<typename...> typename Template, typename... Args>
struct test 
  using type = can_apply_t<Template, Args...>;
;

【讨论】:

【参考方案2】:

如果你可以使用 C++20,concepts 会让事情变得更容易。

template<template<typename...> typename, typename...>
struct test 
  using type = void;
;

template<template<typename...> typename Template, typename... Args>
  requires requires  typename Template<Args...>; 
struct test<Template, Args...> 
  using type = Template<Args...>;
;

Demo.

【讨论】:

...我现在在 yomm2 中所做的许多其他事情也是如此,但我想暂时保持与 C++17 的兼容性。

以上是关于查找是不是可以使用一组参数实例化类模板,arity-wise(在 C++17 中)的主要内容,如果未能解决你的问题,请参考以下文章

使用 COM 的参数化构造函数实例化类

用于编码/解码 arity 0 的密封特征实例的 Circe 实例?

什么时候实例化类模板?

我可以对传递给方法的块强制执行 arity 吗?

在Java中获取参数化类的实例[重复]

模板化类的模板化成员方法可以在类定义之外定义吗