constexpr begin of a std::array
Clash Royale CLAN TAG#URR8PPP
up vote
6
down vote
favorite
I am having trouble understanding why both gcc-8.2.0 and clang-7.0.0 reject the following code (live code here):
#include <array>
int main()
constexpr std::array<int,3> v1,2,3;
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
with the error
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
According to en.cppreference.com, the begin()
member function is declared constexpr
. Is this a compiler bug?
c++ c++17 constexpr
add a comment |Â
up vote
6
down vote
favorite
I am having trouble understanding why both gcc-8.2.0 and clang-7.0.0 reject the following code (live code here):
#include <array>
int main()
constexpr std::array<int,3> v1,2,3;
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
with the error
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
According to en.cppreference.com, the begin()
member function is declared constexpr
. Is this a compiler bug?
c++ c++17 constexpr
use.cbegin
.
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
2
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý makes no difference.
â user2079303
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøýbegin()
andcbegin()
do the same thing on const objects.
â Barry
1 hour ago
so tryauto b=...
and then if it failsconst
. also you changeauto
tostd::....::citerator
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
add a comment |Â
up vote
6
down vote
favorite
up vote
6
down vote
favorite
I am having trouble understanding why both gcc-8.2.0 and clang-7.0.0 reject the following code (live code here):
#include <array>
int main()
constexpr std::array<int,3> v1,2,3;
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
with the error
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
According to en.cppreference.com, the begin()
member function is declared constexpr
. Is this a compiler bug?
c++ c++17 constexpr
I am having trouble understanding why both gcc-8.2.0 and clang-7.0.0 reject the following code (live code here):
#include <array>
int main()
constexpr std::array<int,3> v1,2,3;
constexpr auto b = v.begin(); // error: not a constexpr
return 0;
with the error
error: '(std::array<int, 3>::const_pointer)(& v.std::array<int,3>::_M_elems)'
is not a constant expression (constexpr auto b = v.begin();)
According to en.cppreference.com, the begin()
member function is declared constexpr
. Is this a compiler bug?
c++ c++17 constexpr
c++ c++17 constexpr
edited 1 hour ago
Barry
172k18292537
172k18292537
asked 1 hour ago
linuxfever
1,7381923
1,7381923
use.cbegin
.
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
2
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý makes no difference.
â user2079303
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøýbegin()
andcbegin()
do the same thing on const objects.
â Barry
1 hour ago
so tryauto b=...
and then if it failsconst
. also you changeauto
tostd::....::citerator
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
add a comment |Â
use.cbegin
.
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
2
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý makes no difference.
â user2079303
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøýbegin()
andcbegin()
do the same thing on const objects.
â Barry
1 hour ago
so tryauto b=...
and then if it failsconst
. also you changeauto
tostd::....::citerator
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
use
.cbegin
.â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
use
.cbegin
.â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
2
2
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý makes no difference.
â user2079303
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý makes no difference.
â user2079303
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý
begin()
and cbegin()
do the same thing on const objects.â Barry
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý
begin()
and cbegin()
do the same thing on const objects.â Barry
1 hour ago
so try
auto b=...
and then if it fails const
. also you change auto
to std::....::citerator
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
so try
auto b=...
and then if it fails const
. also you change auto
to std::....::citerator
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
19
down vote
accepted
So let's sidestep std::array
to make this a bit easier:
template <typename T, size_t N>
struct array
T elems[N];
constexpr T const* begin() const return elems;
;
void foo()
constexpr array<int,3> v1, 2, 3;
constexpr auto b = v.begin(); // error
constexpr array<int, 3> global_v1, 2, 3;
constexpr auto global_b = global_v.begin(); // ok
Why is b
an error but global_b
is okay? Likewise, why would b
become okay if we declared v
to be static constexpr
? The problem is fundamentally about pointers. In order to have a constant expression that's a pointer, it has to point to one, known, constant thing, always. That doesn't really work for local variables without static storage duration, since they have fundamentally mutable address. But for function-local statics or globals, they do have one constant address, so you can take a constant pointer to them.
In standardese, from [expr.const]/6:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, [...]
- if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value, and
- [...]
b
is none of those things in the second bullet, so this fails. But global_b
satisfies the bolded condition - as would b
if v
were declared static
.
add a comment |Â
up vote
-3
down vote
Because standard iterators cannot be used in constexpr expressions, there is a proposal for it though which I think is available in c++17 check with c++17 compatible compiler
1
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set-std=c++17
in the options of godbolt.org.)
â Scheff
49 mins ago
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
19
down vote
accepted
So let's sidestep std::array
to make this a bit easier:
template <typename T, size_t N>
struct array
T elems[N];
constexpr T const* begin() const return elems;
;
void foo()
constexpr array<int,3> v1, 2, 3;
constexpr auto b = v.begin(); // error
constexpr array<int, 3> global_v1, 2, 3;
constexpr auto global_b = global_v.begin(); // ok
Why is b
an error but global_b
is okay? Likewise, why would b
become okay if we declared v
to be static constexpr
? The problem is fundamentally about pointers. In order to have a constant expression that's a pointer, it has to point to one, known, constant thing, always. That doesn't really work for local variables without static storage duration, since they have fundamentally mutable address. But for function-local statics or globals, they do have one constant address, so you can take a constant pointer to them.
In standardese, from [expr.const]/6:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, [...]
- if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value, and
- [...]
b
is none of those things in the second bullet, so this fails. But global_b
satisfies the bolded condition - as would b
if v
were declared static
.
add a comment |Â
up vote
19
down vote
accepted
So let's sidestep std::array
to make this a bit easier:
template <typename T, size_t N>
struct array
T elems[N];
constexpr T const* begin() const return elems;
;
void foo()
constexpr array<int,3> v1, 2, 3;
constexpr auto b = v.begin(); // error
constexpr array<int, 3> global_v1, 2, 3;
constexpr auto global_b = global_v.begin(); // ok
Why is b
an error but global_b
is okay? Likewise, why would b
become okay if we declared v
to be static constexpr
? The problem is fundamentally about pointers. In order to have a constant expression that's a pointer, it has to point to one, known, constant thing, always. That doesn't really work for local variables without static storage duration, since they have fundamentally mutable address. But for function-local statics or globals, they do have one constant address, so you can take a constant pointer to them.
In standardese, from [expr.const]/6:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, [...]
- if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value, and
- [...]
b
is none of those things in the second bullet, so this fails. But global_b
satisfies the bolded condition - as would b
if v
were declared static
.
add a comment |Â
up vote
19
down vote
accepted
up vote
19
down vote
accepted
So let's sidestep std::array
to make this a bit easier:
template <typename T, size_t N>
struct array
T elems[N];
constexpr T const* begin() const return elems;
;
void foo()
constexpr array<int,3> v1, 2, 3;
constexpr auto b = v.begin(); // error
constexpr array<int, 3> global_v1, 2, 3;
constexpr auto global_b = global_v.begin(); // ok
Why is b
an error but global_b
is okay? Likewise, why would b
become okay if we declared v
to be static constexpr
? The problem is fundamentally about pointers. In order to have a constant expression that's a pointer, it has to point to one, known, constant thing, always. That doesn't really work for local variables without static storage duration, since they have fundamentally mutable address. But for function-local statics or globals, they do have one constant address, so you can take a constant pointer to them.
In standardese, from [expr.const]/6:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, [...]
- if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value, and
- [...]
b
is none of those things in the second bullet, so this fails. But global_b
satisfies the bolded condition - as would b
if v
were declared static
.
So let's sidestep std::array
to make this a bit easier:
template <typename T, size_t N>
struct array
T elems[N];
constexpr T const* begin() const return elems;
;
void foo()
constexpr array<int,3> v1, 2, 3;
constexpr auto b = v.begin(); // error
constexpr array<int, 3> global_v1, 2, 3;
constexpr auto global_b = global_v.begin(); // ok
Why is b
an error but global_b
is okay? Likewise, why would b
become okay if we declared v
to be static constexpr
? The problem is fundamentally about pointers. In order to have a constant expression that's a pointer, it has to point to one, known, constant thing, always. That doesn't really work for local variables without static storage duration, since they have fundamentally mutable address. But for function-local statics or globals, they do have one constant address, so you can take a constant pointer to them.
In standardese, from [expr.const]/6:
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
- if the value is an object of class type, [...]
- if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object ([expr.add]), the address of a function, or a null pointer value, and
- [...]
b
is none of those things in the second bullet, so this fails. But global_b
satisfies the bolded condition - as would b
if v
were declared static
.
answered 1 hour ago
Barry
172k18292537
172k18292537
add a comment |Â
add a comment |Â
up vote
-3
down vote
Because standard iterators cannot be used in constexpr expressions, there is a proposal for it though which I think is available in c++17 check with c++17 compatible compiler
1
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set-std=c++17
in the options of godbolt.org.)
â Scheff
49 mins ago
add a comment |Â
up vote
-3
down vote
Because standard iterators cannot be used in constexpr expressions, there is a proposal for it though which I think is available in c++17 check with c++17 compatible compiler
1
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set-std=c++17
in the options of godbolt.org.)
â Scheff
49 mins ago
add a comment |Â
up vote
-3
down vote
up vote
-3
down vote
Because standard iterators cannot be used in constexpr expressions, there is a proposal for it though which I think is available in c++17 check with c++17 compatible compiler
Because standard iterators cannot be used in constexpr expressions, there is a proposal for it though which I think is available in c++17 check with c++17 compatible compiler
answered 1 hour ago
Ogunleye Ayowale Pius
114
114
1
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set-std=c++17
in the options of godbolt.org.)
â Scheff
49 mins ago
add a comment |Â
1
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set-std=c++17
in the options of godbolt.org.)
â Scheff
49 mins ago
1
1
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set
-std=c++17
in the options of godbolt.org.)â Scheff
49 mins ago
check with c++17 compatible compiler This is what OP did. You can see it if you follow OP's here link. (She/he has explicitly set
-std=c++17
in the options of godbolt.org.)â Scheff
49 mins ago
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52972533%2fconstexpr-begin-of-a-stdarray%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
use
.cbegin
.â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago
2
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý makes no difference.
â user2079303
1 hour ago
@ÃÂûõúÃÂõùÃÂõÃÂôðÃÂøý
begin()
andcbegin()
do the same thing on const objects.â Barry
1 hour ago
so try
auto b=...
and then if it failsconst
. also you changeauto
tostd::....::citerator
â ÃÂûõúÃÂõù ÃÂõÃÂôðÃÂøý
1 hour ago