c++ - C++20 compile time retrieve size of a vector - Stack Overflow

时间: 2025-01-06 admin 业界

I have a question regarding to the compile time retrieving size of a vector in C++20. Based on C++20 it is possible to create in compile time a vector or a string in the scope of a function.

There is the following piece of code

#include <iostream>
#include <vector>
#include <array>

consteval auto copyVecToArray(){
    std::vector<int> vec{1,2,3,4,5,6,7};
    std::array<int,vec.size()> arr;
    std::copy(std::begin(vec),std::end(vec),std::begin(arr));
    return arr;
}
int main() {
   constexpr auto value = copyVecToArray();
   for(auto el : value){
        std::cout << el << std::endl;
   }
}

Demo which is failed with following compilation error

> <source>:7:28:   in 'constexpr' expansion of
> 'vec.std::vector<int>::size()'
> /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_vector.h:993:32:
> error: the value of 'vec' is not usable in a constant expression   993
> |       { return size_type(this->_M_impl._M_finish -
> this->_M_impl._M_start); }
>       |                          ~~~~~~^~~~~~~ <source>:6:22: note: 'vec' was not declared 'constexpr'
>     6 |     std::vector<int> vec{1,2,3,4,5,6,7};
>       |                      ^~~ <source>:7:28: note: in template argument for type 'long unsigned int'
>     7 |     std::array<int,vec.size()> arr;
>       |                    ~~~~~~~~^~ <source>:8:55: error: no matching function for call to 'begin(int&)'
>     8 |     std::copy(std::begin(vec),std::end(vec),std::begin(arr));
>       |

But if I change a bit the code above and return the size of the vector from a consteval function this successfully compiles.

#include <iostream>
#include <vector>
#include <array>
consteval auto getVec(){
    std::vector<int> vec{1,2,3,4,5,6,7};
    return vec;
}
consteval auto getSize(){
    return getVec().size();
}
consteval auto copyVecToArray(){
    std::array<int,getVec().size()> arr;
    auto vec = getVec();
    std::copy(std::begin(vec),std::end(vec),std::begin(arr));
    return arr;
}
int main() {
   constexpr auto value = copyVecToArray();
   for(auto el : value){
        std::cout << el << std::endl;
   }
}

My question is why using consteval function to retrieve size is ok and not using directly the std::vector::size() method.

Demo 2

I have a question regarding to the compile time retrieving size of a vector in C++20. Based on C++20 it is possible to create in compile time a vector or a string in the scope of a function.

There is the following piece of code

#include <iostream>
#include <vector>
#include <array>

consteval auto copyVecToArray(){
    std::vector<int> vec{1,2,3,4,5,6,7};
    std::array<int,vec.size()> arr;
    std::copy(std::begin(vec),std::end(vec),std::begin(arr));
    return arr;
}
int main() {
   constexpr auto value = copyVecToArray();
   for(auto el : value){
        std::cout << el << std::endl;
   }
}

Demo which is failed with following compilation error

> <source>:7:28:   in 'constexpr' expansion of
> 'vec.std::vector<int>::size()'
> /opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/bits/stl_vector.h:993:32:
> error: the value of 'vec' is not usable in a constant expression   993
> |       { return size_type(this->_M_impl._M_finish -
> this->_M_impl._M_start); }
>       |                          ~~~~~~^~~~~~~ <source>:6:22: note: 'vec' was not declared 'constexpr'
>     6 |     std::vector<int> vec{1,2,3,4,5,6,7};
>       |                      ^~~ <source>:7:28: note: in template argument for type 'long unsigned int'
>     7 |     std::array<int,vec.size()> arr;
>       |                    ~~~~~~~~^~ <source>:8:55: error: no matching function for call to 'begin(int&)'
>     8 |     std::copy(std::begin(vec),std::end(vec),std::begin(arr));
>       |

But if I change a bit the code above and return the size of the vector from a consteval function this successfully compiles.

#include <iostream>
#include <vector>
#include <array>
consteval auto getVec(){
    std::vector<int> vec{1,2,3,4,5,6,7};
    return vec;
}
consteval auto getSize(){
    return getVec().size();
}
consteval auto copyVecToArray(){
    std::array<int,getVec().size()> arr;
    auto vec = getVec();
    std::copy(std::begin(vec),std::end(vec),std::begin(arr));
    return arr;
}
int main() {
   constexpr auto value = copyVecToArray();
   for(auto el : value){
        std::cout << el << std::endl;
   }
}

My question is why using consteval function to retrieve size is ok and not using directly the std::vector::size() method.

Demo 2

Share Improve this question edited yesterday Some programmer dude 409k35 gold badges413 silver badges642 bronze badges asked yesterday getsoublgetsoubl 94512 silver badges29 bronze badges 1
  • fyi, the way people do this is using a lambda to get around exactly that. example with lambda, i am guessing that the rvalues are constexpr but once it becomes an lvalue it is no-longer constexpr, also see Youtube Understanding The constexpr 2-Step - Jason Turner - C++ on Sea 2024 for a neater way to do this without invoking the lambda twice, useful for complex lambdas. – Ahmed AEK Commented yesterday
Add a comment  | 

1 Answer 1

Reset to default 2

Local variables even in consteval functions are not constant expressions because they are able to depend on the values of the function’s parameters. It breaks the type system to let them be such. Nor can you work around this (even when the parameter values aren’t needed) by declaring the std::vector constexpr, since only empty vectors can be complete constant expressions (for deeply technical reasons). Thus the compute-twice trick.