确定包装是否为空

时间:2017-10-20 12:56:54

标签: c++ templates c++17 variadic-templates template-meta-programming

有人可以解释为什么这个静态断言是错误的吗?如何重新定义is_empty以便它按照我想要的方式工作(不改变语法)?默认情况下我想要评估为false的包类型(例如is_empty<int>::value应为false)。

#include <type_traits>
template <typename Pack> struct is_empty : std::false_type {};

template <typename T, template <T...> class Z, T... Is>
struct is_empty<Z<Is...>> : std::true_type {};

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

template <int...> struct Z;

int main() {
    static_assert(is_empty<Z<>>::value);
}

2 个答案:

答案 0 :(得分:10)

为什么这样做?

你可以sizeof...(args)来确定参数包的长度..如果它是0,那么它是空的:

#include <iostream>

template<typename... Args>
void func(Args... args)
{
    std::cout<<(sizeof...(args));
}

int main() {

    func(1, 2, 3);
    func();
    func(1);
    func(1, 2);
    func(1, 2, 3, 4);

    return 0;
}

答案 1 :(得分:2)

问题是T中包含的Z类型无法推断出来。

如果您明确表示并且我不知道如何避免明确的话,则可以使用。

#include <type_traits>

template <typename...>
struct is_empty : std::false_type
 { };

template <typename T, template <T...> class Z, T... Is>
struct is_empty<T, Z<Is...>> : std::true_type
 { };

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

template <int...> struct Z;

int main() {
    static_assert(is_empty<int, Z<>>::value, "!");
}

- 编辑 -

如果您的Z需要第一个参数类型(以std::integer_sequence的方式),则有效;通过这种方式,演绎工作

#include <type_traits>

template <typename>
struct is_empty : std::false_type
 { };

template <typename T, template <typename U, U...> class Z, T... Is>
struct is_empty<Z<T, Is...>>
   : std::integral_constant<bool, sizeof...(Is) == 0U>
 { };

template <typename T, T ...>
struct X
 { };

template <int ... Is>
using Y = X<int>;

int main ()
 {
   static_assert(is_empty<X<int>>::value, "!");
   static_assert(is_empty<Y<>>::value, "!");
 }

- 编辑2 -

在C ++中,17适用于auto

#include <type_traits>

template <typename Pack>
struct is_empty : std::false_type
 { };

template <template <auto...> class Z, auto... Is>
struct is_empty<Z<Is...>> : std::bool_constant<sizeof...(Is) == 0U>
 { };

template <int...>
struct X;

int main()
 {
   static_assert( true  == is_empty<X<>>::value );
   static_assert( false == is_empty<X<1>>::value );
   static_assert( false == is_empty<int>::value );
 }