检测类型是否为零元素数组?

时间:2013-03-19 21:02:34

标签: c++ arrays templates c++11 typetraits

考虑以下功能:

template <typename Type>
void f(const Type& x)

我想在其中做一些特殊的事情(没有专业化),无论传递的类型是空的std::tuple还是空的std::array。对于nu元素的元组,我可以使用std::is_same<Type, std::tuple<>>::value但是我可以用什么技巧来检测零元素数组?

(我正在寻找一种不需要创建另一个函数或类的解决方案,......)

2 个答案:

答案 0 :(得分:6)

您可以使用std::tuple_size,因为它也适用于std::array!见here。只需使用:

std::tuple_size<Type>::value == 0

检查Type是空的std::tuple<>还是空的std::array<T,0>


如果Type既不是std::tuple也不是std::array,那么问题仍然存在。我看到的一般方法是:

constexpr bool IsNotTupleOrArray =
  !std::is_class<Type>::value ||
  std::is_same<Type,ExcludeThisClass>::value ||
  sizeof(Type)>1 || // non-portable, works for GCC 4.8+
  ...;

std::conditional< IsNotTupleOrArray,
                  std::false_type,
                  std::tuple_size<Type> >::type::value;

这基本上意味着您必须明确排除其他类型。例如,is_class<Type>排除所有基本类型,如int,指针等。

答案 1 :(得分:3)

如果你不想在没有专业化的情况下这样做,为什么不用重载呢? ;)专业化功能模板有时(通常)不是一个坏主意。使用一些SFINAE技巧,创建仅在这两个条件适用时选择的重载并不困难。

但是,我已经听到你大声说这不是你想要做的事情:你想要的是if内部的某种f(),如果条件为真,它将被执行,并且当条件为假时将执行的相应else分支。

但是,请注意,这不是static if,而是常规运行时,如果:换句话说,编译器在编译时会100%确定地知道这两个分支中的一个永远不会将被执行(它可能会发出一个恼人的警告),但它必须解析两个分支并证明它们是合法的。

实际上,这意味着您将无法放置依赖于特定类型T(或T的属性)的语句,以便可编译。例如,在下面的代码中compile_time_expression确定类型T是否具有成员函数foo()或成员函数bar()

T obj;
if (compile_time_expression)
{
    obj.foo();
}
else
{
    obj.bar();
}

但是,如果特定T没有 成员函数foo()和成员函数bar(),则上述代码将无法编译:你在这里有一个运行时if,编译器必须解析两个分支并确保它们都是可编译的 - 然后可能优化掉永远不会被执行的分支。

不幸的是,C ++没有任何构造,如静态if(还是?),所以重载+ SFINAE是解决这个问题的正确方法