C ++概念:检查模板实例化

时间:2019-01-14 13:12:42

标签: c++ c++-concepts c++20

假设我具有模板化类型,例如

template<typename A, typename B, typename C>
struct mytype { };

我如何编写一个概念来检查类型是否是该模板的实例化?

template<typename T>
concept MyType = requires(T x) { ??? }

如果不解决老式专用检测器类型或标记器基础类型,我无法找到一种明显的方法。

5 个答案:

答案 0 :(得分:3)

您可以为此定义自己的元功能(类型特征):

template <typename T>
struct is_mytype<T> : std::false_type { };

template <typename A, typename B, typename C>
struct is_mytype<mytype<A, B, C>> : std::true_type { };

template <typename T>
concept MyType = is_mytype<T>::value;

但是说实话,我不知道有没有一种方法可以直接定义这种概念而无需单独的元函数。

答案 1 :(得分:2)

使用C ++ 17类模板参数推导,您应该能够执行以下操作:

template<typename A, typename B, typename C>
struct mytype { };

template<class T>
concept C1 = requires(T x) { 
    { mytype{x} } -> T;
};

mytype{x}使用类模板参数推导来推断ABC,因此如果您可以从{构造一个mytype<A, B, C> {1}}。特别是,如果T是可复制构造的,这是有效的,因为您有一个隐式声明的copy-deduction guide类似于:

mytype

检查template <typename A, typename B, typename C> mytype(mytype<A, B, C>) -> mytype<A, B, C>; 也是构造的T实例,避免与其他推论指南匹配,例如,对于没有mytype的任何类型,该指南都将匹配:

-> T

建议的解决方案不适用于不可复制的类,即使应该使其适用于仅移动类也是如此。


经过测试:

答案 2 :(得分:1)

您可以编写广义特征来检查专业化程度:

library(data.table)
library(lubridate) # <-- only need for `- hours(1)` convenience, not strictly necessary
                   # Could instead do `- 60*60` and not load this package

setDT(data)[                                            #<Turn `data` in to a `data.table`
    J(end=unique(time), start=unique(time) - hours(1)), #<Define the start time=1 hour ago
                                                        #   and end time=current time.
    on=.(time <= end, time >= start),                   #<Join to itself restricting the
                                                        #   time to be within these windows
    list(value = mean(value)),                          #<Calc avg value
    by=.EACHI                                           #<For each join group (time window)
][,
    list(time, value)                                   #<Select the desired columns out
]                                                       # (o'wise you will get two
                                                        # identical "time" columns)

# output
                  time value
                <POSc> <num>
1: 2014-08-09 23:24:13   4.0
2: 2014-08-09 23:25:09   2.5
3: 2014-08-10 00:17:29   3.0
4: 2014-08-10 00:18:47   3.0
5: 2014-08-10 00:27:43   3.0
6: 2014-08-10 00:43:53   3.0

您可以将其归纳为一个广义概念:

template <typename T, template <typename...> class Z>
struct is_specialization_of : std::false_type {};

template <typename... Args, template <typename...> class Z>
struct is_specialization_of<Z<Args...>, Z> : std::true_type {};

template <typename T, template <typename...> class Z>
inline constexpr bool is_specialization_of_v = is_specialization_of<T,Z>::value;

或只是专门的一个:

template<typename T, template <typename...> class Z>
concept Specializes = is_specialization_of_v<T, Z>;

template<typename T>
concept MyType = Specializes<T, mytype>;

答案 3 :(得分:1)

为了简洁:

template<typename T>
concept MyType = requires(T** x) {
    []<typename A, typename B, typename C>(mytype<A, B, C>**){}(x);
};

双指针是避免派生到基类转换所必需的,例如。 struct S : mytype<int, int, int> {}

目前这在 clang 中不起作用,因为它不允许在未评估的上下文中使用 lambda。您可以通过提供辅助变量模板来解决:

template<class T> constexpr auto L = []<typename A, typename B, typename C>(mytype<A, B, C>**){};
template<typename T>
concept MyType = requires(T** x) { L<T>(x); };

只要 mytype 的模板参数都是类型,您可以使用占位符使这更简洁:

template<typename T>
concept MyType = requires(T** x) { [](mytype<auto, auto, auto>**){}(x); };

目前,这只适用于 gcc。

答案 4 :(得分:0)

如果为模板类赋予一些特征,则可以执行以下操作:

b

具有关联概念:

template<typename A, typename B, typename C>
struct mytype {
    using a_type = A;
    using b_type = B;
    using c_type = C;
};

或者,如果mytype具有这些类型的成员,则可以跳过特征:

template <typename T>
concept is_mytype =
    std::is_same_v<
        std::remove_const_t<T>,
        mytype<typename T::a_type, typename T::b_type, typename T::c_type>>;

给出概念:

template<typename A, typename B, typename C>
struct mytype {
    A a_inst;
    B b_inst;
    C c_inst;
};