3

Given the following code:

#include <memory>
#include <locale>

int main() {
    auto source = std::make_unique<int[]>(16);
    auto dest = std::make_unique<int[]>(16);
    auto dp = stdext::checked_array_iterator<int*>(dest.get(), 16);
    std::copy_n(source.get(), 16, dp);
    return 0;
}

It compiles cleanly on Visual Studio 2013 by running cl.exe /EHsc <file>.cpp. However, on Visual Studio 2017 the following errors (among others) are thrown by cl.exe:

vc12.cpp(7): error C2653: 'stdext': is not a class or namespace name
vc12.cpp(7): error C2065: 'checked_array_iterator': undeclared identifier

Why does this code no longer compile?

Lennart
  • 91
  • 7
  • The question might be very specific, but in a big project it took me quite a long time to figure out why it was compiling on VS2013 and no search engine yielded any results. – Lennart Aug 10 '17 at 13:07
  • 1
    Btw, should be `int main`. `void main` is not portable C++. – Baum mit Augen Aug 10 '17 at 13:11
  • @BaummitAugen: Yeah, I tried to keep it minimal. Will add the `int` and the `return`. – Lennart Aug 10 '17 at 13:43
  • You don't need the return, flowing off the end of `main` implicitly returns some value indicating successful termination. – Baum mit Augen Aug 10 '17 at 13:45

2 Answers2

1

The example is missing an #include <iterator>. Technically, it was also missing for Visual Studio 2013 (see Why include what you use), but due to the chain of includes it worked there. Between Visual Studio 2013 and Visual Studio 2017 the includes of the std-headers got revamped.

The example shows #include <locale>. In the old version, #include <iterator> was part of the include-chain of locale, which is no longer the case in Visual Studio 2017.

However, the documentation of VS2017 is hard to find at the moment since it is so new. The important document can be found at doc.microsoft.com, it lists the required header <iterator>.

Lennart
  • 91
  • 7
0

This is included in according to the documentation: https://docs.microsoft.com/en-us/cpp/standard-library/checked-array-iterator-class However you'll need to #include <iterator>.

Though rather than pursuing correcting this, I'd entourage writing standard conformant code. The best way to do that would be to just use a statically allocated array. This will allow you to use C++'s begin, end, and size functions to work with it: https://stackoverflow.com/a/33442842/2642059

There are some cases where that wouldn't be a good suggestion, if a dynamic array is a must have, consider using a vector. If you can't abide a container then using a unique_ptr is a good way to do this, but rather than depending upon checked_array_iterator prefer maintaining your own size:

const size_t sourceSize = 16;
auto source = std::make_unique<int[]>(sourceSize);
auto dest = std::make_unique<int[]>(sourceSize);
std::copy_n(source.get(), sourceSize, dest.get())
Jonathan Mee
  • 35,107
  • 16
  • 95
  • 241