I am trying to implement a constexpr function "add42" that would allow me to do:
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}
That is, add an integer at a given index to an array statically (with constexpr). Since my array "arr" is immutable, I have to actually create a new one from "arr" and my index. That is why I coded this function:
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] ) ;
}
That is, all the integers of my array are recursively unpacked from the array, added 42 if at the right index, and appened at the end of the ARGS list. When this arg list contains all the integers from the array, we are done so we can repack into a new array.
However I get this error (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>'|
Can you explain me what is the problem and how to correct it ?
This question seems similar to C++11: Compile Time Calculation of Array but is not (At least, I am unable to figure out how to use it deirectly): here, I want to create an new array from an already existent one, not from a known sequence of integers.
EDIT
Now I get infinite instantiation, even when no recursion called. Here is a simplified example :
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)] ) ;
}
Why does my compiler try to compile the last function call ?
EDIT 2
Apparently, I have to provide 2 function in order not to confuse the compiler:
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)]) ;
}
But it still does not work:
recursively required from [[name of the second function]]
Apparently, a variadic function cannot call "recursively" one of its overloads. Am I right ? What workaround is possible ?