VS2019 16.10 constexpr

VS2019 16.10 is supposed to include support for the C++20 constexpr for std::string and std::vector. So why doesn't this work? What have I overlooked??

1
2
3
4
5
6
7
8
9
#include <string>
#include <vector>

int main()
{
	constexpr std::string s {"qwe"};

	constexpr std::vector<int> vi {1, 2, 3, 4, 5};
}



1>Source.cpp
1>C:\develop\vc\test64\Source.cpp(6,26): error C2131: expression did not evaluate to a constant
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xstring(4602,50): message : failure was caused by allocated storage not being deallocated
1>C:\develop\vc\test64\Source.cpp(8,32): error C2131: expression did not evaluate to a constant
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\vector(1711,47): message : failure was caused by allocated storage not being deallocated
1>c:\develop\vc\Library\files.hpp(76,18): warning C4018: '<=': signed/unsigned mismatch
1>Done building project "test64.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Last edited on
closed account (z05DSL3A)
Currently updating...

but does this help....
C++ Weekly - Ep 269 - How To Use C++20's constexpr std::vector and std::string
https://www.youtube.com/watch?v=cuFILbHp-RA
From the standard for std::string constructor:


constexpr basic_string(const charT* s, const Allocator& a = Allocator());


So why can't you have:
 
constexpr std::string s("foobar");


??

PS You can do this:

1
2
3
	constinit static const char* const cs[] {"qwe", "foo", "bar"};

	static_assert(std::size(cs) == 3);


but this doesn't really give you anything as cs is built at compile time anyhow:

1
2
3
	const char* const cs[] {"qwe", "foo", "bar"};

	static_assert(std::size(cs) == 3);

Last edited on
closed account (z05DSL3A)
My understanding is that you can construct a string in a constexpr context but the assigned storage can not be carried over to the runtime context. see around 6:10 in the video.
Yes. That seems to be about right from my testing. This compiles OK:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <vector>

constexpr auto f1() {
	const std::vector<int> vi {1, 2, 3};

	return vi.size();
}

int main()
{
	constexpr auto vs {f1()};

	static_assert(vs == 3);
}


So std::vector/std::string cannot be defined themselves as constexpr, but can be used within a constexpr context (eg constexpr function).

But this fails:

1
2
3
4
5
constexpr auto f1() {
	constexpr std::vector<int> vi {1, 2, 3};

	return vi.size();
}


so seems to confirm that can't explicitly define a std::vector/std::string as constexpr.

So can't define at compile time to be used at run-time. Ahh...

Last edited on
OK. So for compile time definition, you can use constexpr with std:array and c-style arrays and with c-style strings (char*) and with std::string_view but not with std::string or std::vector.

Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <array>
#include <string>

int main()
{
	constexpr std::array acs {"abc", "bar"};
	constexpr const char* const cs[] {"xyz", "foo"};

	constexpr std::array ant {1, 2, 3, 4, 5};
	constexpr const int ci[] {6, 7, 8};

	static_assert(cs[0][0] == 'x' && cs[1][1] == 'o');
	static_assert(acs[0][1] == 'b' && acs[1][2] == 'r');

	static_assert(ant[3] == 4);
	static_assert(ci[1] == 7);
}


Which compiles OK so the assertions are true at compile time, so the definitions are compile time.
Last edited on
Topic archived. No new replies allowed.