问题
In the following code, I create an array of length 6 and initialize it with 1, 2 and 3 in the first 3 elements. Then I copy the first 3 elements to the last 3 elements. Then I print all the elements in order.
std::array<int, 6> bar = {1, 2, 3};
int main(){
// Copy the first 3 elements to the last 3 elements
std::copy(bar.begin(), bar.end() - 3, bar.end() - 3);
// Print all the elements of bar
for(auto& i: bar) std::cout << i << std::endl;
}
It works fine, but when I try to make the array constexpr
it no-longer compiles:
constexpr std::array<int, 6> bar = {1, 2, 3};
int main(){
// Copy the first 3 elements to the last 3 elements
std::copy(bar.begin(), bar.end() - 3, bar.end() - 3); // Won't compile!
// Print all the elements of bar
for(auto& i: bar) std::cout << i << std::endl;
}
Compiling with g++ -std=c++14 main.cpp -o main
I get the following error message:
/usr/include/c++/5/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const int*; _OI = const int*]’:
/usr/include/c++/5/bits/stl_algobase.h:438:45: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const int*; _OI = const int*]’
/usr/include/c++/5/bits/stl_algobase.h:471:8: required from ‘_OI std::copy(_II, _II, _OI) [with _II = const int*; _OI = const int*]’
main.cpp:115:53: required from here
/usr/include/c++/5/bits/stl_algobase.h:402:44: error: no matching function for call to ‘std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m(const int*&, const int*&, const int*&)’
_Category>::__copy_m(__first, __last, __result);
^
/usr/include/c++/5/bits/stl_algobase.h:373:9: note: candidate: template<class _Tp> static _Tp* std::__copy_move<_IsMove, true, std::random_access_iterator_tag>::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = false]
__copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
^
/usr/include/c++/5/bits/stl_algobase.h:373:9: note: template argument deduction/substitution failed:
/usr/include/c++/5/bits/stl_algobase.h:402:44: note: deduced conflicting types for parameter ‘_Tp’ (‘int’ and ‘const int’)
_Category>::__copy_m(__first, __last, __result);
I don't understand this error message at all. Is std::copy
not constexpr
? If it isn't, it should be, right? Does my code would work if std::copy
was constexpr
?
回答1:
You should make a constexpr function. constexpr
imply const, but not inside the scope of a constexpr
function.
constexpr auto get_bar() {
std::array<int, 6> bar = {1, 2, 3, 0, 0, 0};
copy(bar.begin(), bar.end() - 3, bar.end() - 3);
return bar;
}
However, you will need to write your own version of copy
because it's not marked as constexpr
in the standard library.
Changing the value of a compile time array does not make sense, it's the same thing as asking the compiler to change the type of a variable at runtime. The compiler don't even exist during runtime. However, a constexpr function is executed by the compiler, so it's still make sense to ask it to mutate values. This is why the code above make sense.
Note that most of std::array
accessors are not constexpr
until C++17.
回答2:
constexpr
imply const
.
Your std::copy
try to modify a const
variable.
--- EDIT ---
The OP ask
I'm implementing something that uses a very large array of precomputed values which wrap around once. I can't do this without printing out values and copy-pasting them into my code?
What about something as follows?
#include <array>
#include <iostream>
template <int ... I>
struct foo
{ std::array<int, 2U*sizeof...(I)> bar { { I..., I... } }; };
int main()
{
foo<2, 3, 5, 7, 11, 13> v;
for ( auto const & i : v.bar )
std::cout << i << ", ";
// the for print 2, 3, 5, 7, 11, 13, 2, 3, 5, 7, 11, 13,
std::cout << std::endl;
}
来源:https://stackoverflow.com/questions/41600157/how-do-you-copy-a-constexpr-array-to-another-constexpr-array-with-stdcopy