【发布时间】:2013-05-23 12:40:34
【问题描述】:
我正在尝试实现一个 constexpr 函数“add42”,它可以让我这样做:
constexpr array<int,5> arr = {1,2,3,4,5};
constexpr array<int,5> arr2 = add42(0,arr); //I want arr2=={43,2,3,4,5}
也就是说,将给定索引处的整数静态添加到数组中(使用 constexpr)。 由于我的数组“arr”是不可变的,我实际上必须从“arr”和我的索引创建一个新数组。这就是我编写这个函数的原因:
template<int DIM, typename... ARGS> auto constexpr
add42(int index, array<int,DIM> intergerArray, ARGS... unpackedIntegers) -> array<int,DIM> {
return
( sizeof...(ARGS)==DIM ) ?
array<int,DIM>( {{unpackedIntegers...}} ) :
( (sizeof...(ARGS)-1)==index ) ?
add42(index, intergerArray, unpackedIntegers..., intergerArray[sizeof...(ARGS)-1]+42 ) :
add42(index, intergerArray, unpackedIntegers..., intergerArray[sizeof...(ARGS)-1] ) ;
}
也就是说,我的数组的所有整数都从数组中递归解包,如果在正确的索引处添加 42,并附加在 ARGS 列表的末尾。当这个 arg 列表包含数组中的所有整数时,我们就完成了,我们可以重新打包到一个新数组中。
但是我得到了这个错误(gcc 4.7.2)
error: no matching function for call to 'add42(int, const std::array<int, 5u>&)'|
note: candidate is:|
template<int DIM, class ... ARGS> constexpr std::array<int, DIM> add42(int, std::array<int, DIM>, ARGS ...)|
note: template argument deduction/substitution failed:|
note: mismatched types 'int' and '#'integer_cst' not supported by dump_type#<type error>'|
你能解释一下是什么问题以及如何解决它吗?
这个问题似乎类似于C++11: Compile Time Calculation of Array 但不是(至少,我无法弄清楚如何直接使用它):在这里,我想从一个已经存在的创建一个新数组> 一个,不是来自已知的整数序列。
编辑
现在我得到了无限的实例化,即使没有调用递归。这是一个简化的例子:
template<size_t DIM, typename... ARGS> auto constexpr
add42(int index, array<int,DIM> integerArray, ARGS... unpackedIntegers) -> array<int,DIM> {
return
( true ) ?
array<int,DIM>( {{unpackedIntegers...}} ) :
add42(index, integerArray, unpackedIntegers..., integerArray[(sizeof...(ARGS)-1)] ) ;
}
为什么我的编译器会尝试编译最后一个函数调用?
编辑 2
显然,为了不混淆编译器,我必须提供 2 个函数:
template<size_t DIM, class... ARGS> constexpr auto
add42(int index, array<int,DIM> integerArray, ARGS... unpackedIntegers) -> typename enable_if<sizeof...(ARGS)==DIM ,array<int,DIM>>::type
{
return array<int,DIM>( {{unpackedIntegers...}} );
}
template<size_t DIM, class... ARGS> constexpr auto
add42(int index, array<int,DIM> integerArray, ARGS... unpackedIntegers) -> typename enable_if<sizeof...(ARGS)!=DIM ,array<int,DIM>>::type
{
return
( sizeof...(ARGS) == index ) ?
add42(index, integerArray, unpackedIntegers..., integerArray[sizeof...(ARGS)]+42) :
add42(index, integerArray, unpackedIntegers..., integerArray[sizeof...(ARGS)]) ;
}
但还是不行:
recursively required from [[name of the second function]]
显然,可变参数函数不能“递归”调用其重载之一。 我对吗 ?有什么解决办法?
【问题讨论】:
-
sizeof返回一个size_t,它是一个无符号整数类型。您可能不想从可能是0的无符号整数中减去1(第一次递归,sizeof...(ARGS)是0)。 -
@DyP 我的错。我编辑删除了这些-1。但还是不行:(
-
使用 constexpr operator[] 和 clang 3.2 它可以工作,尽管你可能最好在第一个 add42 重载中只使用一对大括号——或者只使用 return
{unpackedIntegers...};。 AFAIK 第二对调用复制ctor。 (一对用于 ctor,一对用于成员数组初始化。)