Quantcast
Channel: C++ Team Blog
Viewing all 1541 articles
Browse latest View live

Data Breakpoints – Visual Studio 2017 15.8 Update  

$
0
0

New to Visual Studio 2017 version 15.8, you can now set data breakpoints from within the Locals, Autos, Watch, and Quickwatch windows!  To view official documentation on data breakpoints, check out this post.

Data breakpoints allow you to stop execution when a particular variable stored at a specific memory address changes.  Prior to version 15.8, data breakpoints could only be set via the Breakpoints window. In this window, a data breakpoint can be set by selecting New > Data Breakpoint.. and then entering the address of the desired variable and the number of bytes you want the window to watch. Setting data breakpoints via the Breakpoints window is still valid, especially since this window allows data breakpoints to be combined with Conditions and Actions like any other breakpoint.  However, This requires multiple navigations to bring up the window and its corresponding data breakpoints menu as well as manual inputs for the desired address and byte count.

Image of a data breakpoint being set in the Breakpoint Window

Setting a data breakpoint in the Breakpoint Window

Now, data breakpoints can also be accessed via context menu in the Locals, Autos, Watch, and Quickwatch windows with just two short clicks and no additional user inputs. A data breakpoint can be created in any of the listed windows by right-clicking (or Shift + F10) the desired variable and selecting Break When Value Changes while in break mode. After continuing execution, your code will break again when your specified variable ‘s value changes, and you will also receive a pop-up notification about the change.

Image of a data breakpoint being set in the Watch Window

Setting a data breakpoint in the Watch Window

Ready to try out data breakpoints?  Give us your feedback!

Download Visual Studio 2017 Preview today and give us your feedback on this feature or anything within Visual Studio 2017. Your feedback is a critical part of ensuring that we can deliver a delightful debugging experience. For any questions, reach out to us via Twitter at @visualc or via email at visualcpp@microsoft.com. For any issues or suggestions, please let us know via Help > Send Feedback > Report a Problem in the IDE.


Visual Studio Code C/C++ extension July 2018 Update and IntelliSense auto-configuration for CMake

$
0
0

Last week we shipped the July 2018 update to the C/C++ extension for Visual Studio Code. In this update we added support for a new experimental API that allows build system extensions to pass IntelliSense configuration information to our extension for powering up full IntelliSense experience. You can find the full list of changes in the July 2018 update in the changelog.

As CMake has been the most requested build system for us to provide support for, we’ve been working with vector-of-bool, author of the CMake Tools extension, on an implementation using this new API to provide IntelliSense auto-configuration for CMake, and the changes are now live!

If you are using CMake and are looking for a way to auto-config IntelliSense in the C/C++ extension, be sure to check out the CMake Tools extension. If you are interested in adding IntelliSense support for other build systems, you can learn more about this new API on the npm site. We’re rolling it out as an experimental API and would love any feedback!

IntelliSense auto-configuration for CMake

After both extensions are installed, on opening any folder that contains a CMakeLists.txt file in the root, be sure to follow the steps to let the CMake Tools extension configure your project. Once completed, you will see the following message:

Simply click “Allow” to enable the CMake Tools extension to send IntelliSense configuration over to the C/C++ extension to automatically power up IntelliSense.

If you need to change the IntelliSense provider or disable the one that’s currently in use, you can use the command “C/Cpp: Change Configuration Provider…” in the Command Palette to invoke the list of providers to switch to.

We are very excited about the CMake support (thanks vector-of-bool for partnering with us!), and hope you like it too! We are also looking forward to seeing support for more build systems by leveraging this experimental extension API and any feedback you might have around this API.

Tell us what you think

Download the C/C++ extension for Visual Studio Code, try it out and let us know what you think. File issues and suggestions on GitHub. If you haven’t already provided us feedback, please take this quick survey to help shape this extension for your needs.

Using MSVC in a Docker Container for Your C++ Projects

$
0
0

Containers encapsulate the runtime environment of an application: the file system, environment settings, and virtualized OS are bundled into a package. Docker containers have changed the way we think about build and test environments since they were introduced five years ago.

Visual Studio’s setup and install expert, Heath Stewart, blogs regularly about how to install the Visual Studio Build Tools in a Windows Docker Container. Recently he explained why you won’t find a container image for build tools. Basically, any install that has a workload installed that you aren’t using is going to be bigger than you want. You should tailor an install for your needs. So here we are going to show how to create and use an MSVC Docker container.

The first step is to install Docker Community Edition. If you don’t have Hyper-V enabled, the installer will prompt you to enable it and reboot. After it is installed you need to switch to . The official documentation on how to Install Build Tools into a Container walks through this in much more detail. If you refer to that, stop at step 5 and read the following instructions for creating an MSVC Docker container.

Remember that the VS Build Tools are licensed as a supplement to your existing Visual Studio license. Any images built with these tools should be for your personal use or for use in your organization in accordance with your existing Visual Studio and Windows licenses. Please don’t share these images on a public Docker hub.

Visual Studio Build Tools Dockerfiles

To help you get started in creating Dockerfiles tailored for your needs we have VS Build Tools Dockerfile samples available. Clone that repository locally. There you will find a directory for native-desktop that contains the files we will use as our starting point. If you open that Dockerfile you will see the following line within.

--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended \

That line adds the VCTools workload and additional recommended components that today include CMake and the current Windows SDK. This is a smaller installation than our other sample that includes support for building managed and native projects. To learn more about how you can find the components you need see our additional workloads and components documentation.

Open PowerShell in the native-desktop directory or this repo and build the Docker image.

docker build -t buildtools2017native:latest -m 2GB .

The first time you build the image it will pull down the windowsservercore image, download the build tools, and install them into a local container image.

When this is done you can see the images available locally.

docker images
REPOSITORY                 TAG                            IMAGE ID       CREATED         SIZE
Buildtools2017native       latest                         4ff1cd971254   3 minutes ago   14.9GB
Buildtools2017             latest                         325048ba2240   4 hours ago     22.4GB
microsoft/dotnet-framework 3.5-sdk-windowsservercore-1709 7d89a4baf66c   3 weeks ago     13.2GB

While our buildtoolsmsvc image is large, it is significantly smaller than the VS Build Tools image that includes managed support. Note that these image sizes include the base image so they can be deceiving in terms of actual disk space used.

Trying it all out

Let’s test out our build tools container using a simple little program. Create a new Windows Console Application project in Visual Studio. Add iostream and write out a hello world message as so.

#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
  cout << "I was built in a container..." << endl;
}

We are going to want to deploy this in a future post to a Windows Nano Server container so change the platform target to x64. Go to your project properties and under C/C++ change the Debug Information Format to C7 compatible.

Now we are going to create a build container for our project. Note this line in the Dockerfile we used to create our buildtoolsmsvc image.

ENTRYPOINT C:\BuildTools\Common7\Tools\VsDevCmd.bat &&

The && in that line allows us to pass parameters in when we create a container using this image. Here we will use that to pass in the msbuild command with the options necessary to build our solution. When we start our container for the first time we will map our local source into a directory in the container using the -v option. We will also give the container a name using –name to remember what it is for later. That also makes it easier to run again as we update our source code.

docker run -v C:\source\ConsoleApplication1:c:\ConsoleApplication1 --name ConsoleApplication1 buildtoolsmsvc msbuild c:\ConsoleApplication1\ConsoleApplication1.sln /p:Configuration=Debug /p:Platform=x64

This will spin up a container, use msbuild to build our solution, then exit, and stop the container. You should see output from this process as it runs. Since we mapped to our local volume you will find the build output under your solution directory under x64\Debug. You can run ConsoleApplication1.exe from there and you’ll see the output

I was built in a container...

As you change your sources you can run the container again by running this command (omit the -a attach option if you don’t need to see the output from within the container).

docker start -a ConsoleApplication1

Conclusion

This has gotten us a working MSVC toolset in an isolated, easy-to-use Docker container. You can now spin up additional containers for different projects using the approach outlined above. The disk space used by additional containers using the same base image is miniscule compared to spinning up VMs to get isolated build environments.

In a future post we’ll cover how to take the build output from this process, run it in a container, then attach to the process in the container and debug it.

If you are using containers or doing cloud development with C++ we would love to hear from you. We wouldd appreciate it if you could take a few minutes to take our C++ cloud and container development survey. This will help us focus on topics that are important to you on the blog and in the form of product improvements.

C++ development with Docker containers in Visual Studio Code

$
0
0

Containers allow developers to package up an application with all the parts it needs, such as libraries and other dependencies, and ship it all out as one image. This is especially useful for C++ cross-platform development – with containers you can choose to target a platform that runs on a completely different operating system than your developer machine. And even if they are running on the same OS, the container technology ensures that the application will run on any other machines regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.

Docker is a very popular container platform that makes it easy to create, deploy, and run applications by using containers, and whether you are a seasoned Docker developer or just getting started, Visual Studio Code has great support for working with Docker containers inside the editor.

In this blog post, we are going to walk through how to create a Docker image for C++, start Docker containers, and build and run a C++ “HelloWorld” app in the container using Visual Studio Code.

Install tools

First, let’s get the tools you would need in this walkthrough:

  1. Install Docker on your machine: for Mac, for Windows, or for Linux.
  2. Install Visual Studio Code: https://code.visualstudio.com/.
  3. Docker support for VS Code is provided by an extension. To install the Docker extension, open the Extensions view in VS Code and search for docker to filter the results. Select the Microsoft Docker extension, click on Install, and reload VS Code when completed.

Get our C++ “HelloWorld” app ready

Let’s first work on a C++ “HelloWorld” app, which we’re going to build and run in a Docker container later in this walkthrough. First, create a new folder on your disk and open it in VS Code. Then add a new file named Test.cpp in the folder. Your VS Code window should look like this:

Now let’s put the following content into the Test.cpp file. Save the file and we are done here.

#include <iostream>

int main(int argc, char const *argv[])
{
  std::cout << "Hello Docker container!" << std::endl;
  return 0;
}

Build a Docker image for C++ development

With Docker, you can build images by specifying the step by step commands needed to build the image in a Dockerfile. A Dockerfile is just a text file that contains the build instructions.

1. Create a Dockerfile. The VS Code Docker extension provides a command for adding a Dockerfile to your workspace. With the folder that we created in the previous section opened in VS Code, in the Command Palette (F1), select command Docker: Add Docker files to Workspace to generate Dockerfiledocker-compose.ymldocker-compose.debug.yml, and .dockerignore files for your workspace type.

You will be prompted with a list of platforms or languages you could target. In this walkthrough, let’s choose Other from the list, which will give us a generic Dockerfile from which we can build our C++ specific image.

2. Add build instructions to the Dockerfile. Now we are going to edit the generated Dockerfile with instructions for how the Docker image should be built. The Docker extension enables a great experience for editing Dockerfile by providing auto-completion suggestions, snippets, QuickInfo, and linting for the Docker commands.

In the following sections, we will describe how to build a C++ development environment with GCC and Clang as the compiler. Depending on which compiler you choose, you only need to follow one of the two sections (2.1 or 2.2).

2.1 Build a Docker image for a Clang environment

For building a C++ development environment with the Clang compiler, let’s copy the following content into the Dockerfile, which installs Clang on top of a base Ubuntu image.

# Get the base Ubuntu image from Docker Hub
FROM ubuntu:latest

# Update apps on the base image
RUN apt-get -y update && apt-get install -y

# Install the Clang compiler
RUN apt-get -y install clang

# Copy the current folder which contains C++ source code to the Docker image under /usr/src
COPY . /usr/src/dockertest1

# Specify the working directory
WORKDIR /usr/src/dockertest1

# Use Clang to compile the Test.cpp source file
RUN clang++ -o Test Test.cpp

# Run the output program from the previous step
CMD ["./Test"]

2.1 Build a Docker image for a GCC environment

You can follow similar steps as above to build an image that installs GCC instead of Clang. Or, you could use a base image that has GCC pre-installed to simplify the steps. Let’s copy the following into the Dockerfile to use an image pre-installed with GCC:

# Get the GCC preinstalled image from Docker Hub
FROM gcc:4.9

# Copy the current folder which contains C++ source code to the Docker image under /usr/src
COPY . /usr/src/dockertest1

# Specify the working directory
WORKDIR /usr/src/dockertest1

# Use GCC to compile the Test.cpp source file
RUN g++ -o Test Test.cpp

# Run the program output from the previous step
CMD ["./Test"]

3. Build the Docker image. Now that we have the build instructions in the Dockerfile, we can go ahead build the Docker image. Docker: Build Image is one of the Docker commands the Docker extension provides in the Command Palette.

Another way to invoke the Docker Build command is to right click on the Dockerfile itself in the VS Code Explorer window and select Build Image.

You will then get a prompt asking for the name and version to tag the image.

While the build is in progress, you can see in the VS Code Terminal window how each step specified in the Dockerfile is being executed by Docker. See the following screenshot as an example.

Once completed, you can find the built image under the Images node in the Docker tab in VS Code. The following screenshot shows the image we just built appearing at the top of the image list.

One thing to note is that our base image “Ubuntu:latest” is also in the list. This means it could be reused as the base for other images to be built on top of, with only the image difference stored, which is a huge disk space saving compared with spinning up multiple full VMs.

Run Docker containers

Now that we have an image, let’s try to run it. There’re two ways to run an image using the Docker extension.  Run will execute the image and run the default CMD you specified above. In this case we will Run Interactive which will execute the CMD but also give us an interactive terminal which we can use to see what is going on inside the running container.

In the Docker:Explorer window, we see the container we just started is running:

In the Terminal window, we can see the default CMD we specified in the Dockerfile, which is to run our Test app (CMD [“./Test”]), has been executed by Docker and we got the output just as expected.

Wrap-up

In this blog post, we walked through step by step for how to use the VS Code Docker extension to build Docker images, start Docker containers, and build and run C++ programs in the container. In a future post we’ll cover how to attach to a process in the container and debug it. If you have any suggestions for future topics regarding using C++ with containers, please let us know by leaving comments below.

Also, if you are using containers or doing cloud development with C++ we would love to hear from you. If you could take a few minutes to take our C++ cloud and container development survey, it will help us focus on topics that are important to you on the blog and in the form of product improvements.

std::string_view: The Duct Tape of String Types

$
0
0

Visual Studio 2017 contains support for std::string_view, a type added in C++17 to serve some of the roles previously served by const char * and const std::string& parameters. string_view is neither a “better const std::string&”, nor “better const char *”; it is neither a superset or subset of either. std::string_view is intended to be a kind of universal “glue” — a type describing the minimum common interface necessary to read string data. It doesn’t require that the data be null-terminated, and doesn’t place any restrictions on the data’s lifetime. This gives you type erasure for “free”, as a function accepting a string_view can be made to work with any string-like type, without making the function into a template, or constraining the interface of that function to a particular subset of string types.

tl;dr

string_view solves the “every platform and library has its own string type” problem for parameters. It can bind to any sequence of characters, so you can just write your function as accepting a string view:

void f(wstring_view); // string_view that uses wchar_t's

and call it without caring what stringlike type the calling code is using (and for (char*, length) argument pairs just add {} around them)

// pass a std::wstring:
std::wstring& s;         f(s);

// pass a C-style null-terminated string (string_view is not null-terminated):
wchar_t* ns = "";        f(ns);

// pass a C-style character array of len characters (excluding null terminator):
wchar_t* cs, size_t len; f({cs,len});

// pass a WinRT string
winrt::hstring hs;       f(hs);

f is just an ordinary function, it doesn’t have to be a template.

string_view as a Generic String Parameter

Today, the most common “lowest common denominator” used to pass string data around is the null-terminated string (or as the standard calls it, the Null-Terminated Character Type Sequence). This has been with us since long before C++, and provides clean “flat C” interoperability. However, char* and its support library are associated with exploitable code, because length information is an in-band property of the data and susceptible to tampering. Moreover, the null used to delimit the length prohibits embedded nulls and causes one of the most common string operations, asking for the length, to be linear in the length of the string.

Sometimes const std::string& can be used to pass string data and erase the source, because it accepts std::string objects, const char * pointers, and string literals like “meow”. Unfortunately, const std::string& creates “impedance mismatches” when interacting with code that uses other string types. If you want to talk to COM, you need to use BSTR. If you want to talk to WinRT, you need HSTRING. For NT, UNICODE_STRING, and so on. Each programming domain makes up their own new string type, lifetime semantics, and interface, but a lot of text processing code out there doesn’t care about that. Allocating entire copies of the data to process just to make differing string types happy is suboptimal for performance and reliability.

Example: A Function Accepting std::wstring and winrt::hstring

Consider the following program. It has a library function compiled in a separate .cpp, which doesn’t handle all string types explicitly but still works with any string type.

// library.cpp
#include <stddef.h>
#include <string_view>
#include <algorithm>

size_t count_letter_Rs(std::wstring_view sv) noexcept {
    return std::count(sv.begin(), sv.end(), L'R');
}
// program.cpp
// compile with: cl /std:c++17 /EHsc /W4 /WX
//    /I"%WindowsSdkDir%Include\%UCRTVersion%\cppwinrt" .\program.cpp .\library.cpp
#include <stddef.h>
#include <string.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>

#pragma comment(lib, "windowsapp")
#include <winrt/base.h>

// Library function, the .cpp caller doesn't need to know the implementation
size_t count_letter_Rs(std::wstring_view) noexcept;

int main() {
    std::wstring exampleWString(L"Hello wstring world!");
    exampleWString.push_back(L'\0');
    exampleWString.append(L"ARRRR embedded nulls");
    winrt::hstring exampleHString(L"Hello HSTRING world!");

    // Performance and reliability is improved vs. passing std::wstring, as
    // the following conversions don't allocate and can't fail:
    static_assert(noexcept(std::wstring_view{exampleWString}));
    static_assert(noexcept(std::wstring_view{exampleHString}));

    std::wcout << L"Rs in " << exampleWString
        << L": " << count_letter_Rs(exampleWString) << L"\n";

    // note HStringWrapper->wstring_view implicit conversion when calling
    // count_letter_Rs
    std::wcout << L"Rs in " << std::wstring_view{exampleHString}
        << L": " << count_letter_Rs(exampleHString) << L"\n";
}

Output:

>.\program.exe
Rs in Hello wstring world! ARRRR embedded nulls: 4
Rs in Hello HSTRING world!: 1

The preceding example demonstrates a number of desirable properties of string_view (or wstring_view in this case):

vs. making count_letter_Rs some kind of template
Compile time and code size is reduced because only one instance of count_letter_Rs need be compiled. The interface of the string types in use need not be uniform, allowing types like winrt::hstring, MFC CString, or QString to work as long as a suitable conversion function is added to the string type.
vs. const char *
By accepting string_view, count_letter_Rs need not do a strlen or wcslen on the input. Embedded nulls work without problems, and there’s no chance of in-band null manipulation errors introducing bugs.
vs. const std::string&
As described in the comment above, string_view avoids a separate allocation and potential failure mode, because it passes a pointer to the string’s data, rather than making an entire owned copy of that data.
string_view For Parsers

Another place where non-allocating non-owning string pieces exposed as string_view can be useful is in parsing applications. For example, the C++17 std::filesystem::path implementation that comes with Visual C++ uses std::wstring_view internally when parsing and decomposing paths. The resulting string_views can be returned directly from functions like std::filesystem::path::filename(), but functions like std::filesystem::path::has_filename() which don’t actually need to make copies are natural to write.

inline wstring_view parse_filename(const wstring_view text)
	{	// attempt to parse text as a path and return the filename if it exists; otherwise,
		// an empty view
	const auto first = text.data();
	const auto last = first + text.size();
	const auto filename = find_filename(first, last); // algorithm defined elsewhere
	return wstring_view(filename, last - filename);
	}

class path
	{
public:
	// [...]
	path filename() const
		{	// parse the filename from *this and return a copy if present; otherwise,
			// return the empty path
		return parse_filename(native());
		}
	bool has_filename() const noexcept
		{	// parse the filename from *this and return whether it exists
		return !parse_filename(native()).empty();
		}
	// [...]
	};

In the std::experimental::filesystem implementation written before string_view, path::filename() contains the parsing logic, and returns a std::experimental::filesystem::path. has_filename is implemented in terms of filename, as depicted in the standard, allocating a path to immediately throw it away.

Iterator Debugging Support

In debugging builds, MSVC’s string_view implementation is instrumented to detect many kinds of buffer management errors. The valid input range is stamped into string_view’s iterators when they are constructed, and unsafe iterator operations are blocked with a message describing what the problem was.

// compile with cl /EHsc /W4 /WX /std:c++17 /MDd .\program.cpp
#include <crtdbg.h>
#include <string_view>

int main() {
    // The next 3 lines cause assertion failures to go to stdout instead of popping a dialog:
    _set_abort_behavior(0, _WRITE_ABORT_MSG);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);

    // Do something bad with a string_view iterator:
    std::string_view test_me("hello world");
    (void)(test_me.begin() + 100); // dies
}
>cl /nologo /MDd /EHsc /W4 /WX /std:c++17 .\test.cpp
test.cpp

>.\test.exe
xstring(439) : Assertion failed: cannot seek string_view iterator after end

Now, this example might seem a bit obvious, because we’re clearly incrementing the iterator further than the input allows, but catching mistakes like this can make debugging much easier in something more complex. For example, a function expecting to move an iterator to the next ‘)’:

// compile with cl /EHsc /W4 /WX /std:c++17 /MDd .\program.cpp
#include <crtdbg.h>
#include <string_view>

using std::string_view;

string_view::iterator find_end_paren(string_view::iterator it) noexcept {
    while (*it != ')') {
        ++it;
    }

    return it;
}

int main() {
    _set_abort_behavior(0, _WRITE_ABORT_MSG);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
    string_view example{"malformed input"};
    const auto result = find_end_paren(example.begin());
    (void)result;
}
>cl /nologo /EHsc /W4 /WX /std:c++17 /MDd .\program.cpp
program.cpp

>.\program.exe
xstring(358) : Assertion failed: cannot dereference end string_view iterator
Pitfall #1: std::string_view doesn’t own its data, or extend lifetime

Because string_view doesn’t own its actual buffer, it’s easy to write code that assumes data will live a long time. An easy way to demonstrate this problem is to have a string_view data member. For example, a struct like the following is dangerous:

struct X {
    std::string_view sv; // Danger!
    explicit X(std::string_view sv_) : sv(sv_) {}
};

because a caller can expect to do something like:

int main() {
    std::string hello{"hello"};
    X example{hello + " world"}; // forms string_view to string destroyed at the semicolon
    putc(example.sv[0]); // undefined behavior
}

In this example, the expression `hello + ” world”` creates a temporary std::string, which is converted to a std::string_view before the constructor of X is called. X stores a string_view to that temporary string, and that temporary string is destroyed at the end of the full expression constructing `example`. At this point, it would be no different if X had tried to store a const char * which was deallocated. X really wants to extend the lifetime of the string data here, so it must make an actual copy.

There are of course conditions where a string_view member is fine; if you’re implementing a parser and are describing a data structure tied to the input, this may be OK, as std::regex does with std::sub_match. Just be aware that string_view’s lifetime semantics are more like that of a pointer.

Pitfall #2: Type Deduction and Implicit Conversions

Attempting to generalize functions to different character types by accepting basic_string_view instead of string_view or wstring_view prevents the intended use of implicit conversion. If we modify the program from earlier to accept a template instead of wstring_view, the example no longer works.

// program.cpp
// compile with: cl /std:c++17 /EHsc /W4 /WX
//    /I"%WindowsSdkDir%Include\%UCRTVersion%\cppwinrt" .\program.cpp
#include <stddef.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <locale>
#include <stdexcept>
#include <string>
#include <string_view>

#pragma comment(lib, "windowsapp")
#include <winrt/base.h>

template<class Char>
size_t count_letter_Rs(std::basic_string_view<Char> sv) noexcept {
    return std::count(sv.begin(), sv.end(),
        std::use_facet<std::ctype<Char>>(std::locale()).widen('R'));
}

int main() {
    std::wstring exampleWString(L"Hello wstring world!");
    winrt::hstring exampleHString(L"Hello HSTRING world!");
    count_letter_Rs(exampleWString); // no longer compiles; can't deduce Char
    count_letter_Rs(std::wstring_view{exampleWString}); // OK
    count_letter_Rs(exampleHString); // also no longer compiles; can't deduce Char
    count_letter_Rs(std::wstring_view{exampleHString}); // OK
}

In this example, we want exampleWString to be implicitly converted to a basic_string_view<wchar_t>. However, for that to happen we need template argument deduction to deduce CharT == wchar_t, so that we get count_letter_Rs. Template argument deduction runs before overload resolution or attempting to find conversion sequences, so it has no idea that basic_string is at all related to basic_string_view, and type deduction fails, and the program does not compile. As a result, prefer accepting a specialization of basic_string_view like string_view or wstring_view rather than a templatized basic_string_view in your interfaces.

In Closing

We hope string_view will serve as an interoperability bridge to allow more C++ code to seamlessly communicate. We are always interested in your feedback. Should you encounter issues please let us know through Help > Report A Problem in the product, or via Developer Community. Let us know your suggestions through UserVoice. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

Visual Studio Code C/C++ extension August 2018 Update

$
0
0

Late last week we shipped the August 2018 update  to the C/C++ extension for Visual Studio Code. This update included support for “Just My Code” symbol search, a gcc-x64 option in the intelliSenseMode setting, and many bug fixes. You can find the full list of changes in the release notes.

“Just My Code” symbol search

Keyboard shortcut Ctrl+T in Visual Studio Code lets you jump to any symbols in the entire workspace.

We have heard feedback that sometimes it is desired to have the system header symbols excluded from this search. In this update, we enabled “Just My Code” symbol search to filter out system symbols, which offers a cleaner result list and significantly speeds up symbol search in large codebases, and as such we’ve made this behavior the default.

If you need symbol search to also include system headers, simply toggle the C_Cpp.workspaceSymbols setting in the VS Code Settings file (File > Preferences > Settings).

Tell us what you think

Download the C/C++ extension for Visual Studio Code, try it out and let us know what you think. File issues and suggestions on GitHub. If you haven’t already provided us feedback, please take this quick survey to help shape this extension for your needs.

Q&A: How to specialize std::sort by binding the comparison function

$
0
0

This post is part of a regular series of posts where the C++ product team here at Microsoft and other guests answer questions we have received from customers. The questions can be about anything C++ related: Visual C++, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc. Today’s Q&A is by Herb Sutter.

Question

A reader recently asked: I am trying to specialize std::sort by binding the comparison function.
I first tried:

auto sort_down = bind(sort<>,_1,_2,[](int x, int y){return x > y;});

It couldn’t infer the parameter types. So then I tried:

auto sort_down = bind(sort<vector<int>::iterator,function<int(int)>>,
                      _1,_2,[](int x, int y){return x > y;});

Is there a straightforward way to do this?
Another example:

auto f = bind(plus<>(), _1, 1)

Here bind has no trouble deducing the template arguments in this case, but when I use a function template for the original callable, it’s not so happy. Just wanting to be consistent with this usage.

Answer

First, the last sentence is excellent: We should definitely be aiming for a general consistent answer where possible so we can spell the same thing the same way throughout our code.

In questions about binders, the usual answer is to use a lambda function directly instead – and usually a generic lambda is the simplest and most flexible. A lambda additionally lets you more directly express how to take its parameters when it’s invoked – by value, by reference, by const, and so forth, instead of resorting to things like std::ref as we do when we use binders.

For the second example, you can write f as a named lambda this way:

auto f = [](const auto& x){ return x+1; };

For the first example, you can write sort_down as a named lambda like this:

auto sort_down = [](auto a, auto b){ return sort(a, b, [](int x, int y){return x > y;}); };

Note the way to give a name to a lambda: assign it to an auto variable, which you can give any name you like. In this case I take a and b by value because we know they’re intended to be iterators which are supposed to be cheap to copy.

The nice thing about lambdas is they allow exactly what you asked for: consistency. To be consistent, code should use lambdas exclusively, never bind. As of C++14, which added generic lambdas, lambdas can now do everything binders can do and more, so there is never a reason to use the binders anymore.

Note that the old binders bind1st and bind2nd were deprecated in C++11 and removed in C++17. Granted, we have not yet deprecated or removed std::bind itself, but I wouldn’t be surprised to see that removed too. Although bind can be convenient and it’s not wrong to use it, there is no reason I know of to use it in new code that is not now covered by lambdas, and since lambdas can do things that binders cannot, we should encourage and use lambdas consistently.

As a side point, notice that the “greater than” comparison lambda

[](int x, int y){return x > y;}

expects integer values only, and because of the glories of the C integer types it can give the wrong results because of truncating (e.g., if passed a long long) and/or sign conversion (e.g., a 32-bit unsigned 3,000,000,000 is greater than 5, but when converted to signed is less than 5). It would be better written as

[](const auto& x, const auto& y){return x > y;}

or in this case

std::greater<>{}

Thanks to Stephan Lavavej for comments on this answer.

Your questions?

If you have any question about C++ in general, please comment about it below. Someone in the community may answer it, or someone on our team may consider it for a future blog post. If instead your question is about support for a Microsoft product, you can provide feedback via Help > Report A Problem in the product, or via Developer Community.

Use the official Boost.Hana with MSVC 2017 Update 8 compiler

$
0
0

We would like to share a progress update to our previous announcement regarding enabling Boost.Hana with MSVC compiler. Just as a quick background, Louis Dionne, the Boost.Hana author, and us have jointly agreed to provide a version of Boost.Hana in vcpkg to promote usage of the library among more C++ users from the Visual C++ community. We’ve identified a set of blocking bugs and workarounds and called them out in our previous blog, and stated that as we fix the remaining bugs, we will gradually update the version of Boost.Hana in vcpkg, ultimately removing it and replacing it with master repo. We can conduct this development publicly in vcpkg without hindering new users who take a dependency on the library.

Today, we’re happy to announce that the vcpkg version of Boost.Hana now just points to the official master repo, instead of our fork.

With VS2017 Update 8 MSVC compiler, the Boost.Hana official repo with this pull request or later will build clean. We recommend you take the dependency via vcpkg.

For full transparency, below is where we stand with respect to active bugs and used source workarounds as of August 2018:

Source workarounds in place

There are 3 remaining workarounds in Boost.Hana official repo for active bugs in VS2017 Update 8 compiler:

// Multiple copy/move ctors
#define BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654

// Forward declaration of class template member function returning decltype(auto)
#define BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735

// Parser incorrectly parses a comparison operation as a template id
// This issue only impacts /permissive- or /std:c++17
#define&nbsp;BOOST_HANA_WORKAROUND_MSVC_RDPARSER_TEMPLATEID_616568

Removed 23 source workarounds that are no longer necessary for VS2017 Update 8 release. Full details for more information.

// Fixed by commit f4e60b2ecc169b0a5ec51d713125801adae24bc2, 20180323
// Note, the workaround requires /Zc:externConstexpr
#define BOOST_HANA_WORKAROUND_MSVC_NONTYPE_TEMPLATE_PARAMETER_INTERNAL

// Fixed by commit c9999d916f1d73bc852de709607b2ca60e76a4c9, 20180513
#define BOOST_HANA_WORKAROUND_MSVC_CONSTEXPR_NULLPTR
#define BOOST_HANA_WORKAROUND_MSVC_CONSTEXPR_ARRAY_399280

// error C2131: expression did not evaluate to a constant
// test\_include\auto\for_each.hpp
#define BOOST_HANA_WORKAROUND_MSVC_FOR_EACH_DISABLETEST

// test\functional\placeholder.cpp
#define BOOST_HANA_WORKAROUND_MSVC_CONSTEXPR_ADDRESS_DISABLETEST
#define BOOST_HANA_WORKAROUND_MSVC_CONSTEXPR_ARRAY_DISABLETEST

// Fixed by commit 5ef87ec5d20b45552784a40fe455c04c257c7b08, 20180516
// Generic lambda preparsing and static capture
#define BOOST_HANA_WORKAROUND_MSVC_GENERIC_LAMBDA_NAME_HIDING_616190

// Fixed by commit 9c4869e61b5ad301f1fe265193241d2c74729a1c, 20180518
// ICE when try to give warning on the format string for printf
// example\misc\printf.cpp
#define BOOST_HANA_WORKAROUND_MSVC_PRINTF_WARNING_506518

// Fixed by commit 095130d02c8805517bbaf93d92415041eecbca00, 20180521
// decltype behavior difference when comparing character array and std::string
// test\orderable.cpp
#define BOOST_HANA_WORKAROUND_MSVC_DECLTYPE_ARRAY_616099

// Fixed by commit a488f9dccbfb4ceade4104c0d8d00e25d6ac7d88, 20180521
// Member with array type
// test\issues\github_365.cpp
#define BOOST_HANA_WORKAROUND_MSVC_GITHUB365_DISABLETEST

// Fixed by commit 7a572ef6535746f1cee5adaa2a41edafca6cf1bc, 20180522
// Member with the same name as the enclosing class
// test\issues\github_113.cpp
#define BOOST_HANA_WORKAROUND_MSVC_PARSEQNAME_616018_DISABLETEST

// Fixed by commit 3c9a06971bf4c7811db1a21017ec509a56d60e59, 20180524
#define BOOST_HANA_WORKAROUND_MSVC_VARIABLE_TEMPLATE_EXPLICIT_SPECIALIZATION_616151

// error C3520: 'Args': parameter pack must be expanded in this context
// example\tutorial\integral-branching.cpp
#define BOOST_HANA_WORKAROUND_MSVC_LAMBDA_CAPTURE_PARAMETERPACK_616098_DISABLETEST

// Fixed by commit 5b1338ce09f7827e5b9248bcba2f519043044fef, 20180529
// Narrowing warning on constant float
// example\core\convert\embedding.cpp
#define BOOST_HANA_WORKAROUND_MSVC_NARROWING_CONVERSION_FLOAT_616032

// Fixed by commit be8778ab26957ae7c6a36376a9ae2d049d64a095, 20180611
// Pack expansion of decltype
// example\hash.cpp
#define BOOST_HANA_WORKAROUND_MSVC_PACKEXPANSION_DECLTYPE_616094

// Fixed by commit 5fd2bf807a0320167c72d9960b32d823a634c04d, 20180613
// Parser error when using '{}' in template arguments
#define BOOST_HANA_WORKAROUND_MSVC_PARSE_BRACE_616118

// Fixed by commit ce4f90349574b4acc955cf1eb04d7dc6a03a568e, 20180614
// Generic lambda and sizeof...
// test\type\is_valid.cpp
#define BOOST_HANA_WORKAROUND_MSVC_GENERIC_LAMBDA_RETURN_TYPE_269943

// Return type of generic lambda is emitted as a type token directly after pre-parsing
#define BOOST_HANA_WORKAROUND_MSVC_GENERIC_LAMBDA_RETURN_TYPE_610227

// Fixed by commit 120bb866980c8a1abcdd41653fa084d6c8bcd327, 20180615
// Nested generic lambda
// test\index_if.cpp
#define BOOST_HANA_WORKAROUND_MSVC_NESTED_GENERIC_LAMBDA_615453

// Fixed by commit 884bd374a459330721cf1d2cc96d231de3bc68f9, 20180615
// Explicit instantiation involving decltype
// example\tutorial\introspection.cpp
#define BOOST_HANA_WORKAROUND_MSVC_DECLTYPE_EXPLICIT_SPECIALIZATION_508556

// Fixed by commit ff9ef6d9fe43c54f7f4680a2701ad73de18f9afb, 20180620
// constexpr function isn't evaluated correctly in SFINAE context
#define BOOST_HANA_WORKAROUND_MSVC_SFINAE_CONSTEXPR_616157

// Fixed by commit 19c35b8c8a9bd7dda4bb44cac1d9d446ed1b20ac, 20180625
// Pack expansion of decltype
// test\detail\variadic\at.cpp
// test\detail\variadic\drop_into.cpp
#define BOOST_HANA_WORKAROUND_MSVC_PACKEXPANSION_DECLTYPE_616024

Bugs remaining in the compiler

  • There are 3 active bugs with the VS2017 Update 8 release. This is down from 25 active bugs from Update 7 release.
  • We plan to fix these remaining bugs by the VS2017 Update 9 release later this year.

What’s next…

  • Throughout the remaining updates of Visual Studio 2017, we will continue to exhaust the remaining MSVC bugs that block upstream version of the Boost.Hana library.
  • We will continue to provide status updates on our progress. Next update will be when we release VS2017 Update 9.
  • We will ensure that users who take dependency on this library in vcpkg will not be affected by our work.
  • Where are we with enabling Range-v3 with MSVC?
    • Similarly, we are tracking all Range-v3 blocking bugs in the compiler and fixing them. Our plan is to fix them all in the remaining VS2017 Update 9 release.

In closing

We’d love for you to download Visual Studio 2017 version 15.8 and try out all the new C++ features and improvements. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems with MSVC in Visual Studio 2017 please let us know through Help > Report A Problem in the product, or via Developer Community. Let us know your suggestions through UserVoice. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

Thank you,

Xiang Fan, Ulzii Luvsanbat


std::optional: How, when, and why

$
0
0

This post is part of a regular series of posts where the C++ product team here at Microsoft and other guests answer questions we have received from customers. The questions can be about anything C++ related: MSVC toolset, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc. Today’s post is by Casey Carter.

C++17 adds several new “vocabulary types” – types intended to be used in the interfaces between components from different sources – to the standard library. MSVC has been shipping implementations of std::optionalstd::any, and std::variant since the Visual Studio 2017 release, but we haven’t provided any guidelines on how and when these vocabulary types should be used. This article on std::optional is the first of a series that will examine each of the vocabulary types in turn.

The need for “sometimes-a-thing”

How do you write a function that optionally accepts or returns an object? The traditional solution is to choose one of the potential values as a sentinel to indicate the absence of a value:

void maybe_take_an_int(int value = -1); // an argument of -1 means "no value"
int maybe_return_an_int(); // a return value of -1 means "no value"

This works reasonably well when one of the representable values of the type never occurs in practice. It’s less great when there’s no obvious choice of sentinel and you want to be able to pass all representable values. If that’s the case, the typical approach is to use a separate boolean to indicate whether the optional parameter holds a valid value:

void maybe_take_an_int(int value = -1, bool is_valid = false);
void or_even_better(pair<int, bool> param = std::make_pair(-1, false));
pair<int, bool> maybe_return_an_int();

This is also feasible, but awkward. The “two distinct parameters” technique of maybe_take_an_int requires the caller to pass two things instead of one to represent a single notion, and fails silently when the caller forgets the bool and simply calls maybe_take_an_int(42). The use of pair in the other two functions avoids those problems, but it’s possible for the user of the pair to forget to check the bool and potentially use a garbage value in the int. Passing std::make_pair(42, true) or std::make_pair(whatever, false) is also hugely different than passing 42 or nothing – we’ve made the interface hard to use.

The need for “not-yet-a-thing”

How do you write a class with a member object whose initialization is delayed, i.e., optionally contains an object? For whatever reason, you do not want to initialize this member in a constructor. The initialization may happen in a later mandatory call, or it may happen only on request. When the object is destroyed the member must be destroyed only if it has been initialized. It’s possible to achieve this by allocating raw storage for the member object, using a bool to track its initialization status, and doing horrible placement new tricks:

using T = /* some object type */;

struct S {
  bool is_initialized = false;
  alignas(T) unsigned char maybe_T[sizeof(T)];

  void construct_the_T(int arg) {
    assert(!is_initialized);
    new (&maybe_T) T(arg);
    is_initialized = true;
  }

  T& get_the_T() {
    assert(is_initialized);
    return reinterpret_cast<T&>(maybe_T);
  }

  ~S() {
    if (is_initialized) {
      get_the_T().~T(); // destroy the T
    }
  }

  // ... lots of code ...
};

The "lots of code" comment in the body of S is where you write copy/move constructors/assignment operators that do the right thing depending on whether the source and target objects contain an initialized T. If this all seems horribly messy and fragile to you, then give yourself a pat on the back – your instincts are right. We’re walking right along the cliff’s edge where small mistakes will send us tumbling into undefined behavior.

Another possible solution to many of the above problems is to dynamically allocate the “optional” value and pass it via pointer – ideally std::unique_ptr. Given that we C++ programmers are accustomed to using pointers, this solution has good usability: a null pointer indicates the no-value condition, * is used to access the value, std::make_unique<int>(42) is only slightly awkward compared to return 42 and unique_ptr handles the deallocation for us automatically. Of course usability is not the only concern; readers accustomed to C++’s zero-overhead abstractions will immediately pounce upon this solution and complain that dynamic allocation is orders of magnitude more expensive than simply returning an integer. We’d like to solve this class of problem without requiring dynamic allocation.

optional is mandatory

C++17’s solution to the above problems is std::optionaloptional<T> directly addresses the issues that arise when passing or storing what may-or-may-not-currently-be an object. optional<T> provides interfaces to determine if it contains a T and to query the stored value. You can initialize an optional with an actual T value, or default-initialize it (or initialize with std::nullopt) to put it in the “empty” state. optional<T> even extends T‘s ordering operations <><=>= – where an empty optional compares as less than any optional that contains a T – so you can use it in some contexts exactly as if it were a Toptional<T> stores the T object internally, so dynamic allocation is not necessary and in fact explicitly forbidden by the C++ Standard.

Our functions that need to optionally pass a T would be declared as:

void maybe_take_an_int(optional<int> potential_value = nullopt); 
  // or equivalently, "potential_value = {}"
optional<int> maybe_return_an_int();

Since optional<T> can be initialized from a T value, callers of maybe_take_an_int need not change unless they were explicitly passing -1 to indicate “not-a-value.” Similarly, the implementation of maybe_return_an_int need only change places that are returning -1 for “not-a-value” to instead return nullopt (or equivalently {}).

Callers of maybe_return_an_int and the implementation of maybe_take_an_int require more substantial changes. You can ask explicitly if an instance of optional holds a value using either the has_value member or by contextual conversion to bool:

optional<int> o = maybe_return_an_int();
if (o.has_value()) { /* ... */ }
if (o) { /* ... */ } // "if" converts its condition to bool

Once you know that the optional contains a value, you can extract it with the * operator:

if (o) { cout << "The value is: " << *o << '\n'; }

or you can use the value member function to get the stored value or a bad_optional_access exception if there is none, and not bother with checking:

cout << "The value is: " << o.value() << '\n';

or the value_or member function if you’d rather get a fallback value than an exception from an empty optional:

cout << "The value might be: " << o.value_or(42) << '\n';

All of which together means we cannot inadvertently use a garbage value as was the case for the “traditional” solutions. Attempting to access the contained value of an empty optional results in an exception if accessed with the value() member, or undefined behavior if accessed via the * operator that can be caught by debug libraries and static analysis tools. Updating the “old” code is probably as simple as replacing validity tests like value == not_a_value_sentinel and if (is_valid) with opt_value.has_value() and if (opt_value) and replacing uses with *opt_value.

Returning to the concrete example, your function that looks up a string given an integer can simply return optional<string>. This avoids the problems of the suggested solutions; we can

  • easily discern the no-value case from the value-found case, unlike for the “return a default value” solution,
  • report the no-value case without using exception handling machinery, which is likely too expensive if such cases are frequent rather than exceptional,
  • avoid leaking implementation details to the caller as would be necessary to expose an “end” iterator with which they could compare a returned iterator.

Solving the delayed initialization problem is straightforward: we simply add an optional<T> member to our class. The standard library implementer is responsible for getting the placement new handling correct, and std::optional already handles all of the special cases for the copy/move constructors/assignment operators:

using T = /* some object type */;

struct S {
  optional<T> maybe_T;    

  void construct_the_T(int arg) {
    // We need not guard against repeat initialization;
    // optional's emplace member will destroy any 
    // contained object and make a fresh one.        
    maybe_T.emplace(arg);
  }

  T& get_the_T() { 
    assert(maybe_T);
    return *maybe_T;    
    // Or, if we prefer an exception when maybe_T is not initialized:
    // return maybe_T.value();
  }

  // ... No error-prone handwritten special member functions! ...
};

optional is particularly well-suited to the delayed initialization problem because it is itself an instance of delayed initialization. The contained T may be initialized at construction, or sometime later, or never. Any contained T must be destroyed when the optional is destroyed. The designers of optional have already answered most of the questions that arise in this context.

Conclusions

Any time you need a tool to express “value-or-not-value”, or “possibly an answer”, or “object with delayed initialization”, you should reach into your toolbox for std::optional. Using a vocabulary type for these cases raises the level of abstraction, making it easier for others to understand what your code is doing. The declarations optional<T> f(); and void g(optional<T>); express intent more clearly and concisely than do pair<T, bool> f(); or void g(T t, bool is_valid);. Just as is the case with words, adding to our vocabulary of types increases our capacity to describe complex problems simply – it makes us more efficient.

If you have any questions, please feel free to post in the comments below. You can also send any comments and suggestions directly to the author via e-mail at cacarter@microsoft.com, or Twitter @CoderCasey. Thank you!

Using C++17 Parallel Algorithms for Better Performance

$
0
0

This post is part of a regular series of posts where the C++ product team here at Microsoft and other guests answer questions we have received from customers. The questions can be about anything C++ related: MSVC toolset, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc. Today’s post is by Billy O’Neal.

C++17 added support for parallel algorithms to the standard library, to help programs take advantage of parallel execution for improved performance. MSVC first added experimental support for some algorithms in 15.5, and the experimental tag was removed in 15.7.

The interface described in the standard for the parallel algorithms doesn’t say exactly how a given workload is to be parallelized. In particular, the interface is intended to express parallelism in a general form that works for heterogeneous machines, allowing SIMD parallelism like that exposed by SSE, AVX, or NEON, vector “lanes” like that exposed in GPU programming models, and traditional threaded parallelism.

Our parallel algorithms implementation currently relies entirely on library support, not on special support from the compiler. This means our implementation will work with any tool currently consuming our standard library, not just MSVC’s compiler. In particular, we test that it works with Clang/LLVM and the version of EDG that powers Intellisense.

How to: Use Parallel Algorithms

To use the parallel algorithms library, you can follow these steps:

  1. Find an algorithm call you wish to optimize with parallelism in your program. Good candidates are algorithms which do more than O(n) work like sort, and show up as taking reasonable amounts of time when profiling your application.
  2. Verify that code you supply to the algorithm is safe to parallelize.
  3. Choose a parallel execution policy. (Execution policies are described below.)
  4. If you aren’t already, #include <execution> to make the parallel execution policies available.
  5. Add one of the execution policies as the first parameter to the algorithm call to parallelize.
  6. Benchmark the result to ensure the parallel version is an improvement. Parallelizing is not always faster, particularly for non-random-access iterators, or when the input size is small, or when the additional parallelism creates contention on external resources like a disk.

For the sake of example, here’s a program we want to make faster. It times how long it takes to sort a million doubles.

// compile with:
//  debug: cl /EHsc /W4 /WX /std:c++latest /Fedebug /MDd .\program.cpp
//  release: cl /EHsc /W4 /WX /std:c++latest /Ferelease /MD /O2 .\program.cpp
#include <stddef.h>
#include <stdio.h>
#include <algorithm>
#include <chrono>
#include <random>
#include <ratio>
#include <vector>

using std::chrono::duration;
using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
using std::milli;
using std::random_device;
using std::sort;
using std::vector;

const size_t testSize = 1'000'000;
const int iterationCount = 5;

void print_results(const char *const tag, const vector<double>& sorted,
                   high_resolution_clock::time_point startTime,
                   high_resolution_clock::time_point endTime) {
  printf("%s: Lowest: %g Highest: %g Time: %fms\n", tag, sorted.front(),
         sorted.back(),
         duration_cast<duration<double, milli>>(endTime - startTime).count());
}

int main() {
  random_device rd;

  // generate some random doubles:
  printf("Testing with %zu doubles...\n", testSize);
  vector<double> doubles(testSize);
  for (auto& d : doubles) {
    d = static_cast<double>(rd());
  }

  // time how long it takes to sort them:
  for (int i = 0; i < iterationCount; ++i)
  {
    vector<double> sorted(doubles);
    const auto startTime = high_resolution_clock::now();
    sort(sorted.begin(), sorted.end());
    const auto endTime = high_resolution_clock::now();
    print_results("Serial", sorted, startTime, endTime);
  }
}

Parallel algorithms depend on available hardware parallelism, so ensure you test on hardware whose performance you care about. You don’t need a lot of cores to show wins, and many parallel algorithms are divide and conquer problems that won’t show perfect scaling with thread count anyway, but more is still better. For the purposes of this example, we tested on an Intel 7980XE system with 18 cores and 36 threads. In that test, debug and release builds of this program produced the following output:

.\debug.exe
Testing with 1000000 doubles...
Serial: Lowest: 1349 Highest: 4.29497e+09 Time: 310.176500ms
Serial: Lowest: 1349 Highest: 4.29497e+09 Time: 304.714800ms
Serial: Lowest: 1349 Highest: 4.29497e+09 Time: 310.345800ms
Serial: Lowest: 1349 Highest: 4.29497e+09 Time: 303.302200ms
Serial: Lowest: 1349 Highest: 4.29497e+09 Time: 290.694300ms

C:\Users\bion\Desktop>.\release.exe
Testing with 1000000 doubles...
Serial: Lowest: 2173 Highest: 4.29497e+09 Time: 74.590400ms
Serial: Lowest: 2173 Highest: 4.29497e+09 Time: 75.703500ms
Serial: Lowest: 2173 Highest: 4.29497e+09 Time: 87.839700ms
Serial: Lowest: 2173 Highest: 4.29497e+09 Time: 73.822300ms
Serial: Lowest: 2173 Highest: 4.29497e+09 Time: 73.757400ms

Next, we need to ensure our sort call is safe to parallelize. Algorithms are safe to parallelize if the “element access functions” — that is, iterator operations, predicates, and anything else you ask the algorithm to do on your behalf follow the normal “any number of readers or at most one writer” rules for data races. Moreover, they must not throw exceptions (or throw exceptions rarely enough that terminating the program if they do throw is OK).

Next, choose an execution policy. Currently, the standard includes the parallel policy, denoted by std::execution::par, and the parallel unsequenced policy, denoted by std::execution::par_unseq. In addition to the requirements exposed by the parallel policy, the parallel unsequenced policy requires that your element access functions tolerate weaker than concurrent forward progress guarantees. That means that they don’t take locks or otherwise perform operations that require threads to concurrently execute to make progress. For example, if a parallel algorithm runs on a GPU and tries to take a spinlock, the thread spinning on the spinlock may prevent other threads on the GPU from ever executing, meaning the spinlock may never be unlocked by the thread holding it, deadlocking the program. You can read more about the nitty gritty requirements in the [algorithms.parallel.defns] and [algorithms.parallel.exec] sections of the C++ standard. If in doubt, use the parallel policy. In this example, we are using the built-in double less-than operator which doesn’t take any locks, and an iterator type provided by the standard library, so we can use the parallel unsequenced policy.

Note that the Visual C++ implementation implements the parallel and parallel unsequenced policies the same way, so you should not expect better performance for using par_unseq on our implementation, but implementations may exist that can use that additional freedom someday.

In the doubles sort example above, we can now add

#include <execution>

to the top of our program. Since we’re using the parallel unsequenced policy, we add std::execution::par_unseq to the algorithm call site. (If we were using the parallel policy, we would use std::execution::par instead.) With this change the for loop in main becomes the following:

for (int i = 0; i < iterationCount; ++i)
{
  vector<double> sorted(doubles);
  const auto startTime = high_resolution_clock::now();
  // same sort call as above, but with par_unseq:
  sort(std::execution::par_unseq, sorted.begin(), sorted.end());
  const auto endTime = high_resolution_clock::now();
  // in our output, note that these are the parallel results:
  print_results("Parallel", sorted, startTime, endTime);
}

Last, we benchmark:

.\debug.exe
Testing with 1000000 doubles...
Parallel: Lowest: 6642 Highest: 4.29496e+09 Time: 54.815300ms
Parallel: Lowest: 6642 Highest: 4.29496e+09 Time: 49.613700ms
Parallel: Lowest: 6642 Highest: 4.29496e+09 Time: 49.504200ms
Parallel: Lowest: 6642 Highest: 4.29496e+09 Time: 49.194200ms
Parallel: Lowest: 6642 Highest: 4.29496e+09 Time: 49.162200ms

.\release.exe
Testing with 1000000 doubles...
Parallel: Lowest: 18889 Highest: 4.29496e+09 Time: 20.971100ms
Parallel: Lowest: 18889 Highest: 4.29496e+09 Time: 17.510700ms
Parallel: Lowest: 18889 Highest: 4.29496e+09 Time: 17.823800ms
Parallel: Lowest: 18889 Highest: 4.29496e+09 Time: 20.230400ms
Parallel: Lowest: 18889 Highest: 4.29496e+09 Time: 19.461900ms

The result is that the program is faster for this input. How you benchmark your program will depend on your own success criteria. Parallelization does have some overhead and will be slower than the serial version if N is small enough, depending on memory and cache effects, and other factors specific to your particular workload. In this example, if I set N to 1000, the parallel and serial versions run at approximately the same speed, and if I change N to 100, the serial version is 10 times faster. Parallelization can deliver huge wins but choosing where to apply it is important.

Current Limitations of the MSVC Implementation of Parallel Algorithms

We built the parallel reverse, and it was 1.6x slower than the serial version on our test hardware, even for large values of N. We also tested with another parallel algorithms implementation, HPX, and got similar results. That doesn’t mean it was wrong for the standards committee to add those to the STL; it just means the hardware our implementation targets didn’t see improvements. As a result we provide the signatures for, but do not actually parallelize, algorithms which merely permute, copy, or move elements in sequential order. If we get feedback with an example where parallelism would be faster, we will look into parallelizing these. The affected algorithms are:

  • copy
  • copy_n
  • fill
  • fill_n
  • move
  • reverse
  • reverse_copy
  • rotate
  • rotate_copy
  • swap_ranges

Some algorithms are unimplemented at this time and will be completed in a future release. The algorithms we parallelize in Visual Studio 2017 15.8 are:

  • adjacent_difference
  • adjacent_find
  • all_of
  • any_of
  • count
  • count_if
  • equal
  • exclusive_scan
  • find
  • find_end
  • find_first_of
  • find_if
  • for_each
  • for_each_n
  • inclusive_scan
  • mismatch
  • none_of
  • reduce
  • remove
  • remove_if
  • search
  • search_n
  • sort
  • stable_sort
  • transform
  • transform_exclusive_scan
  • transform_inclusive_scan
  • transform_reduce

Design Goals for MSVC’s Parallel Algorithms Implementation

While the standard specifies the interface of the parallel algorithms library, it doesn’t say at all how algorithms should be parallelized, or even on what hardware they should be parallelized. Some implementations of C++ may parallelize by using GPUs or other heterogeneous compute hardware if available on the target. copy doesn’t make sense for our implementation to parallelize, but it does make sense on an implementation that targets a GPU or similar accelerator. We value the following aspects in our implementation:

Composition with platform locks

Microsoft previously shipped a parallelism framework, ConcRT, which powered parts of the standard library. ConcRT allows disparate workloads to transparently use the hardware available, and lets threads complete each other’s work, which can increase overall throughput. Basically, whenever a thread would normally go to sleep running a ConcRT workload, it suspends the chore it’s currently executing and runs other ready-to-run chores instead. This non-blocking behavior reduces context switches and can produce higher overall throughput than the Windows threadpool our parallel algorithms implementation uses. However, it also means that ConcRT workloads do not compose with operating system synchronization primitives like SRWLOCK, NT events, semaphores, COM single threaded apartments, window procedures, etc. We believe that is an unacceptable trade-off for the “by default” implementation in the standard library.

The standard’s parallel unsequenced policy allows a user to declare that they support the kinds of limitations lightweight user-mode scheduling frameworks like ConcRT have, so we may look at providing ConcRT-like behavior in the future. At the moment however, we only have plans to make use of the parallel policy. If you can meet the requirements, you should use the parallel unsequenced policy anyway, as that may lead to improved performance on other implementations, or in the future.

Usable performance in debug builds

We care about debugging performance. Solutions that require the optimizer to be turned on to be practical aren’t suitable for use in the standard library. If I add a Concurrency::parallel_sort call to the previous example program, ConcRT’s parallel sort a bit faster in release but almost 100 times slower in debug:

for (int i = 0; i < iterationCount; ++i)
{
  vector<double> sorted(doubles);
  const auto startTime = high_resolution_clock::now();
  Concurrency::parallel_sort(sorted.begin(), sorted.end());
  const auto endTime = high_resolution_clock::now();
  print_results("ConcRT", sorted, startTime, endTime);
}
C:\Users\bion\Desktop>.\debug.exe
Testing with 1000000 doubles...
ConcRT: Lowest: 5564 Highest: 4.29497e+09 Time: 23910.081300ms
ConcRT: Lowest: 5564 Highest: 4.29497e+09 Time: 24096.297700ms
ConcRT: Lowest: 5564 Highest: 4.29497e+09 Time: 23868.098500ms
ConcRT: Lowest: 5564 Highest: 4.29497e+09 Time: 24159.756200ms
ConcRT: Lowest: 5564 Highest: 4.29497e+09 Time: 24950.541500ms

C:\Users\bion\Desktop>.\release.exe
Testing with 1000000 doubles...
ConcRT: Lowest: 1394 Highest: 4.29496e+09 Time: 19.019000ms
ConcRT: Lowest: 1394 Highest: 4.29496e+09 Time: 16.348000ms
ConcRT: Lowest: 1394 Highest: 4.29496e+09 Time: 15.699400ms
ConcRT: Lowest: 1394 Highest: 4.29496e+09 Time: 15.907100ms
ConcRT: Lowest: 1394 Highest: 4.29496e+09 Time: 15.859500ms
Composition with other programs on the system and parallelism frameworks

Scheduling in our implementation is handled by the Windows system thread pool. The thread pool takes advantage of information not available to the standard library, such as what other threads on the system are doing, what kernel resources threads are waiting for, and similar.
It chooses when to create more threads, and when to terminate them. It’s also shared with other system components, including those not using C++.

For more information about the kinds of optimizations the thread pool does on your (and our) behalf, check out Pedro Teixeira’s talk on the thread pool, as well as official documentation for the CreateThreadpoolWork, SubmitThreadpoolWork, WaitForThreadpoolWorkCallbacks, and CloseThreadpoolWork functions.

Above all, parallelism is an optimization

If we can’t come up with a practical benchmark where the parallel algorithm wins for reasonable values of N, it will not be parallelized. We view being twice as fast at N=1’000’000’000 and 3 orders of magnitude slower when N=100 as an unacceptable tradeoff. If you want “parallelism no matter what the cost” there are plenty of other implementations which work with MSVC, including HPX and Threading Building Blocks.

Similarly, the C++ standard permits parallel algorithms to allocate memory, and throw std::bad_alloc when they can’t acquire memory. In our implementation we fall back to a serial version of the algorithm if additional resources can’t be acquired.

Benchmark parallel algorithms and speed up your own applications

Algorithms that take more than O(n) time (like sort) and are called with larger N than 2,000 are good places to consider applying parallelism. We want to make sure this feature behaves as you expect; please give it a try. If you have any feedback or suggestions for us, let us know. We can be reached via the comments below, via email (visualcpp@microsoft.com) and you can provide feedback via Help > Report A Problem in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

Exploring Clang Tooling, Part 0: Building Your Code with Clang

$
0
0

This post is part of a regular series of posts where the C++ product team and other guests answer questions we have received from customers. The questions can be about anything C++ related: MSVC toolset, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc.

Today’s post is by guest author Stephen Kelly, who is a developer at Havok, a contributor to Qt and CMake and a blogger. This is the first post in a series where he is sharing his experience using Clang tooling in his current team.

Conformance and Compatibility

During the long development of C++ compilers so far, a few compilers have dominated in mainstream domains. MSVC 6 and GCC 2.95 have sometimes been described as ‘too successful’. Their success has produced lasting effect of driving C++ adoption, but they had many incompatibilities with each other, resulting in beautiful walled gardens. In some cases (such as omitting the typename keyword inside templates) this made development tasks more convenient, even if the resulting code was divergent from the C++ standard or from GCC. For developers working on code intended to be portable between different platforms, this has been a lasting annoyance – colleagues would check-in code without the required typename keyword, causing other colleagues who use a more conforming compiler to repair the code.

On Unix-like platforms where GCC dominated, standards conformance has held a higher status in part due to Free Software culture of many compatible tools (and people!) which can collaborate in the venue of the standard. Clang, a more recent entry into the field of C++ compilers, shared that aim of standards conformance but gained marketshare for several reasons, among them licence choice, implementation language choice, cross-compilation, improved diagnostic messages etc. Such competition has benefited both GCC and Clang as they match each other in terms of compliance and developer utility. Part of the strategy employed by Clang was to implement compatibility with GCC in terms of behavior, GCC bugs which are relied upon in standard Unix headers, and implementing a ‘compiler driver’ which is compatible on the command line with GCC in terms of warning flags and other compile options.

MSVC compiler has not been left behind on any front and is implementing and driving standards conformance for developers who value portability. The /permissive- option is standard conformant modulo bugs. Those remaining bugs will be resolved as releases continue.

Another development in the last several years is the emergence of tooling APIs for C++ based on Clang. Clang developers have created tooling which can be used to mechanically refactor large amounts of C++ code, including clang-tidy and clang-format. Custom tools based on clang-tidy in particular is the subject of the follow-up posts in this blog series.

Acquiring the Clang/LLVM Tools

Together with the use of Clang as a viable compiler for production use on Windows for multiple web browsers, all of this leaves the question of how you can benefit from Clang tooling. If your codebase has only ever been built with the MSVC compiler, the code must first be made buildable with Clang.

Installers of Clang for Windows are available here. One of the ways Clang has been able to repeat its success on Windows is to implement compatibility with MSVC. The Clang installer for Windows includes two ‘compiler drivers’. clang++ is GCC compatible even on Windows and may be used with a codebase which relies on MinGW. clang-cl is the second compiler driver shipped with the Clang installer and is compatible with the MSVC compiler driver. This compatibility appears in terms of accepting command line flags in the style of cl.exe and in terms of running Clang in a permissive mode in line with cl.exe.

After running the Clang installer, a toolset file is required to instruct Visual Studio 2017 to use clang-cl.exe instead of the native cl.exe. The ‘LLVM Compiler Toolchain’ extension for Visual Studio 2017 must be installed to enable the toolchain.

After installing the ‘LLVM Compiler Toolchain’ the platform toolset can be changed to llvm in Visual Studio, or by specifying it in your buildsystem generator, such as CMake with cmake .. -T llvm.

Using MSVC compiler’s /permissive- flag

Some of the C++ conformance issues detected by Clang are also detected by recent MSVC releases with the /permissive- flag. So, a first step to getting code to build with Clang may be to first build it with MSVC Conformance mode. The downside of this is that MSVC Conformance mode is more strict than Clang in some cases (because Clang attempts to emulate permissive MSVC). Certain MSVC behaviors such as incorrect two-phase-lookup is allowed by Clang-CL by default and rejected by MSVC Conformance mode.

Iterative Conformance

A more conforming mode of Clang-CL can be activated by adding the compile flags -fno-delayed-template-parsing -Werror=microsoft -Werror=typename-missing. Even after turning Microsoft diagnostics into errors, individual such diagnostics can be disabled if required by adding -Wno- versions of the documented flag such as -Wno-microsoft-sealed. Note that such a flag must appear after the -Werror=microsoft option.

Even with the compatibility that Clang-CL provides, a fallback option can be used to instruct the compiler to compile with CL.exe if required.

Several features of Clang may need to be enabled in the buildsystem to build the code. Use of intrinsics such as _mm_shuffle_epi8 requires the use of the -msse4.1 flag or similar.

As with enabling compiler warning on a codebase which has never used them before, the most sensible approach is to start building with Clang using the most permissive settings necessary, and then introduce more conformance over time.

If your interest in Clang is limited to making use of semantically-rich tooling, it is important to remember that your code does not need to run after it is compiled. It also does not need to link, or even to compile – judicious use of ifdefs can be used to make most of your code reachable to Clang tooling while limiting the effect on code which is too affected to compile, or on code you don’t control. Some parts of the Windows headers do not compile with Clang yet. That is likely to affect your code too. Certain efforts within Microsoft are addressing these issues in shipped headers.

Porting existing C++ code

Here are some issues that may occur when porting your code to build with Clang or /permissive-, as you increase the level of standard conformance in your build:

Only one user-defined conversion may be invoked implicitly
MSVC in permissive mode accepts C++ code which invokes two implicit conversions at once (instead of the standard-conforming one). Clang-CL does not accept such double-conversions. This can arise when converting between two distinct string types for example (implicitly to, then from const char*).
Both result statements in a ternary expression must have the same type
Where ternaries are used with two different result types, it will be necessary to ensure that both result types are the same without implicit conversion. This can occur with simple wrapper types, or more complex expressions, such as when using a smart pointer which converts implicitly to a pointer type:
smart_pointer<int> func(bool b)
{
    int* defaultPtr = nullptr;
    smart_pointer<int> sp;
    return b ? sp : defaultPtr;
}
Missing `typename` and `template` keywords
C++ requires the user to use the typename keyword in certain template contexts in order to disambiguate between types and values in permissive mode and requires the template keyword to disambiguate between template functions and comparisons.

In the case of variables within templates, the solution is usually to use auto instead of adding the template keyword.
This can also occur when using type traits such as std::remove_reference. Developers might write (or copy from elsewhere in your codebase), code such as

template<typename T>
void doSomething(T t)
{
    std::remove_reference<T>::type value = input;
    ++value;
    return value;
}

and Clang rightly issues a diagnostic and recommends use of the typename keyword.

However, at this point it is obvious that developers are not going to remember to add such keywords unless they are reminded of it, so perhaps a different strategy of teaching developers to use std::remove_reference_t instead, and omit the trailing ::type. It is simpler all-round and more portable. Similar transformations can be introduced for any custom type traits used in your code.

Excessive typename keyword
Similarly, sometimes MSVC accepts a typename keyword where it should not.

Unfortunately, there are opposite cases where Clang requires a template keyword where it should not, so getting this right can at times require an #ifdef.

Static variables defined inside if statement
MSVC incorrectly accepts code such as
if (static bool oneTimeInit = true)
{
}

In a modern codebase, this should be changed to

if (static bool oneTimeInit = true; oneTimeInit)
{
}

This requires the use of the /std:c++17 flag when compiling with MSVC.

Implicit deletion of defaulted constructor
Clang does not allow user-defined but defaulted constructors where they are required to initialize a union.

The solution here is to actually define the constructor instead of defaulting it:

B::B()
{        
}
Clang does not accept the for each extension
The solution here is to use cxx_range_for instead. Replace
for each (auto item in container)

With

for (auto item : container)
Qualify lookup in template-dependent base
MSVC incorrectly accepts (and disambiguates) use of declarations from template-dependent bases, though Clang does not. This is again due to lax implementation of two-phase lookup. The solution here is to prefix such calls with this-> or the name of the base class.
Always-false static asserts
static_assert(false) is sometimes attempted by developers who wish to issue an informative error message if there is an attempt to instantiate a template which should not be instantiated. Unfortunately it doesn’t work with two phase lookup. This is accepted by MSVC, but not by Clang. The solution is to make the value dependent on the template type.
Specialization in different scope to declaration
MSVC allows specialization of a C++ template in different a namespace to the one it was declared in. Clang does not allow this. The specialization should be in the same namespace as the initial template.
template<typename T>
struct Templ
{
};

namespace NS {

template<>
struct Templ<int>
// error: class template specialization of 'Templ' must occur at global scope
{
};

}

Conclusion

It is important to realize that being able to build code with Clang is useful even if you can not run it (due to #ifdefs or dependency issues). Running Clang-built code opens up the possibility of using Clang sanitizers for example, but just being able to compile the code with Clang enables use of source-transformation tools such as clang-tidy, clazy and clang-format. Further blog posts in this series will explore workflows for source-to-source transformation with Clang.

Please leave a comment if you encountered other changes you needed to make in your code to compile with Clang-CL!

Parallel Custom Build Tools in Visual Studio 2017

$
0
0

This post was written by Olga Arkhipova.

Many projects need to use additional tools during their build to generate sources for further compilation or perform other custom build tasks. VC projects have always supported Custom Build Tool integration, but it had some limitations. One of the popular requests on UserVoice is Allow custom build tools to run in parallel. Another problem is that often custom build outputs need to be passed to other build tools (for instance, some tools can generate C/C++ sources, which need to be passed to the compiler) and there was no easy way to specify that.

To solve these problems, we added support for parallel execution of custom build tools and new options for easier build integration in Visual Studio 2017 15.8.

Also, one of the most common build customizations is copying files. Before, we recommended using “Custom Build Step” or “Custom Build Tool” and specifying copy commands there. Now you can use simple Copy File options.

Custom Build Tool Options

If you are familiar with Custom Build Tool usage, you can skip this section and go to New Custom Build Tool Options.

Custom Build Tool options are not visible in the “Project Properties” until you have at least one file using “Custom Build Tool” as its “Item Type”. You can set it in the file’s “General” properties:

Custom Build Tool Item Type

As for other tools, you can set “Custom Build Tool” properties for each file, but usually it is easier to set them at the project configuration level, so they apply to all files which use “Custom Build Tool”. Note that you can use MSBuild Well-known Item Metadata there to specify file specific options. Unfortunately, you cannot use other item properties as they are not guaranteed to be defined before their usage.

Custom Build Tool Properties

Command Line

Specifies the command(s) to execute in cmd.exe. If you want several commands to be executed for the same file, you can add them to a script file or just enter them in the property editor, each command on a separate line:

Custom Command Line

Description

Specifies a message to be printed before execution of the command(s), optional. It is added as ‘’echo” command, so if you want to use “>” symbol, it needs to be escaped: “^>”.

Outputs

Specifies the output files the custom build tool generates.

Additional Dependencies

Specifies any additional input files to use for the custom build tool. Required for incremental build.

Link Objects

Specify whether the Inputs and outputs files with specific extensions (.obj, .lib, .res, .rsc) are passed to the linker.
This property was added in VS 2010 to maintain the behavior of pre-msbuild vc projects (VS 2009 and before) where file extensions determined which build action was performed on them.

MSBuild is operating on items included into a particular named ItemGroup (Item Type), so we recommend using the new “Add Outputs to Item Type” property instead.

Treat Output As Content

Specify whether the output file is a deployable content. Only used in projects supporting packaging (Universal Windows).

Content Root Folder

Content root folder to use for packaging.

Execute After, Execute Before

Define when to execute Custom Build Tool and Custom Build Step commands. For historical reasons they are executed at the same time.
The options are using msbuild target names, which requires you to have some understanding of msbuild targets execution order during build. There is a long list of the targets in the dropdown you can select from and you can type the target name there as well, but usually you just need to select one of the following targets which represent 3 main steps of C++ build:

  • BuildGenerateSources
  • BuildCompile
  • BuildLink

If your custom build needs to be executed in more precise time, you might need to look at your detailed (or binary) build log – you’ll see all targets executed during build and their order.

New Custom Build Tool Options

Add Outputs to Item Type

If you want custom build outputs to become inputs for another build operation, you can specify it here.

For instance, if you want the outputs to be compiled, you need to add them to “C/C++ compiler” item type. You also need to make Custom Build Tool to be executed before C/C++ compilation by setting “Execute After” to “BuildGenerateSources” or “Execute Before” to “BuildCompile”.

Build in Parallel

Specifies that this item can be built in parallel with other custom build tool items.

Maximum Processes

Maximum number of CPU cores to use for parallel build. A value of 0 utilizes all available processors.

Maximum Batch size

Maximum number of items to execute together in one cmd.exe process during parallel build. A value of 0 divides items evenly into parallel batches. A value of 1 disables batching.
Launching a cmd.exe process takes some time, so larger batches will improve performance if the custom build tool processes items quickly. If your custom build takes significant time, disabling batching will give you better error reporting.

Copy File Options

If you need to copy a file to one or several locations during build, first you need to change its “Item Type” to “Copy file” and Apply. Then you’ll see “Copy File” properties.

Copy File Item Type

Again, you can define the options for individual files, or, if they are similar, for project configuration using MSBuild Well-known Item Metadata:

Copy File Item Properties

Destination Directories

You can specify one or several directories (separated by ‘;’) to copy the file to. The default is $(OutDir).

Destination File Name

You can specify the file name for the destination file(s). The default is the same as source: %(Filename)%(Extension).

Other properties are the similar to Custom Build Tool and Custom Build step: you can set if the destination file(s) should be included into a package and when to copy the files during build.

Send Us Feedback

Please download Visual Studio 2017 version 15.8 and try the new Custom Build Tool and Copy File functionality. We would love to know how it is working for you. Please give us feedback via the comments below or via email (visualcpp@microsoft.com). For general issues please Report a Problem.

STL Features and Fixes in VS 2017 15.8

$
0
0

15.7 was our first feature complete C++17 library (except floating-point <charconv>), and in 15.8 we have addressed large numbers of outstanding bugs. As usual, we’ve maintained a detailed list of the STL fixes that are available. Visual Studio 2017 15.8 is available at https://visualstudio.microsoft.com/vs/.

New Features
  • Implemented floating-point from_chars() in C++17 <charconv>. It’s approximately 40% faster than the CRT’s strtod()/strtof().
  • Implemented C++20 feature-test macros in the compiler and STL (except for __has_cpp_attribute which will be implemented in the future). The feature-test macros are always provided regardless of the Standard mode option (/std:c++14 vs. /std:c++17 etc.) – that is, individual feature-test macros are defined (or not) according to the Standard mode option and fine-grained options, but there’s no option for enabling or disabling feature-test macros in their entirety.
  • Implemented std::is_aggregate.
  • Added officially supported hooks to allow user iterator type interaction with iterator debugging, already in use by the Guidelines Support Library. See gsl::span for an example implementation of the following customization points, or the type _String_view_iterator in the internal header <xstring>.
    The customization points are, given a const user_iterator_type cit; and a user_iterator_type it:
    _Verify_range(cit, cit)
    Requests that the iterator type check that the parameters form a valid [First, Last) range iterator pair. The standard library provides a version for pointers under _ITERATOR_DEBUG_LEVEL != 0. We strongly recommend this customization point be implemented as a “hidden friend function”, as demonstrated in the gsl::span example.
    cit._Verify_offset(difference_type off)
    For random-access iterators, verifies that cit + off is a valid iterator. Typically used to provide better diagnostics of the form “the iterator range passed to this algorithm was invalid” rather than “the iterator was incremented off the end of the range”.
    static constexpr bool user_iterator_type::_Unwrap_when_unverified
    Declares to the standard library whether an iterator type wants to be “unchecked” or “unwrapped” even if it can’t be verified in advance by _Verify_range or _Verify_offset. For example, the standard containers set this to true if and only if _ITERATOR_DEBUG_LEVEL == 0. This allows an iterator type to request range checks even in release builds (as desired by gsl::span). If this member is not present, it defaults to false.
    cit._Unwrapped()
    Returns an “unchecked” or “unwrapped” iterator denoting the same element as cit. This will be called by the standard library after a _Verify_range or _Verify_offset call, or if _Unwrap_when_unverified is true.
    it._Seek_to(cit) / it._Seek_to(return value from _Unwrapped())
    Moves the position of the “wrapped” or “checked” iterator it to the position of the “unwrapped” / “unchecked” iterator supplied. This is generally not intended to perform range checks. This allows algorithms that return iterators like std::fill_n to form their return values without needing each iterator operation in the body of the algorithm to be subject to debugging checks.
  • The header structure of the STL was changed to allow use of a subset of the library in conditions where the user can’t link with msvcp140.dll, such as driver development. (Previously the hard dependency on msvcp and pragma detect mismatch were injected by our base configuration header included by everything.) The following headers are now considered “core” and don’t inject our runtime dependencies (though we do still assume some form of CRT headers are present):
    • <cstddef>
    • <cstdlib>
    • <initializer_list>
    • <ratio>
    • <type_traits>

    We aren’t actually driver developers ourselves and are interested in feedback in this area if there are things we can do to make these more usable in constrained environments.

Correctness Fixes
  • Implemented Library Issues 2510, 2729, and 2958 for pair and tuple, constraining their assignment operators. This implementation contained a minor regression affecting assignments to std::pair from a type that implicitly converts to std::pair. We’ve fixed that regression for VS 2019 16.0 and are planning to backport the fix to VS 2017 15.9. In the meantime, if you encounter that compiler error, explicitly converting to std::pair is a workaround.
  • Because user iterators can now officially participate in the iterator debugging system, the _SCL_SECURE_NO_WARNINGS family of warnings has been removed. The previously-pseudo-documented struct _Is_checked_helper remains present in order to avoid breaking user specializations, but it is no longer used by the library directly.
  • Changed num_get overloads to store default values in the event of a failed parse, as the standard requires.
  • Fixed incorrect values numeric_limits<integral>::is_modulo and numeric_limits<floating-point>::tinyness_before.
  • Rewrote several streambuf operations to resolve cases where the streambuf would become confused; for example, cases where seekg(0) would not reset the streambuf position even when the current offset was nonzero.
  • Fixed cases where basic_filebuf would become confused when set to some multibyte locales; the lead byte table was populated using the “fake POSIX support” locale function _ismbslead, but then used the standard locale function _isleadbyte later in processing, corrupting the state of the basic_filebuf.
  • Fixed conditions where one could form a corrupted basic_stringbuf (or stringstream) by forcing it to attempt to represent a string of more than INT_MAX characters. The INT_MAX size restriction unfortunately must remain due to ABI compatibility, but at least we now consistently enforce that restriction.
  • Overhauled std::ws to Do What The Standard Says.
  • The off-by-default warning C4365 “conversion from ‘type_1’ to ‘type_2’, signed/unsigned mismatch” is now supported by the STL.
  • Fixed a case C4365 found in put_money where a narrowed wchar_t was emitted instead of the proper raw wchar_t.
  • Fixed creating an istreambuf_iterator::proxy returning the value stored in the proxy rather than returning the value one would expect from a copied istreambuf_iterator.
  • Fixed a case where linear_congruential_engine would use unsigned int to do intermediate calculations even when unsigned int could not properly store the intermediate values.
  • Fixed linear_congruential_engine::seed() to Do What The Standard Says.
  • Changed parallel algorithms’ partitioning behavior to not special case the foreground thread, improving performance in situations where the system threadpool detects an I/O bound workload and decides to oversubscribe the machine.
  • Fixed a race condition in std::async that could cause crashes or deadlocks.
  • Fixed C++17 std::filesystem‘s support .obj containing a __declspec(dllexport), causing unusual conditions like .exes with export tables.
  • Fixed recursive_directory_iterator::disable_recursion_pending() not being reset after an increment operation.
  • Fixed a long-standing bug that caused aligned_storage to treat requests for alignment greater than alignof(max_align_t) as requests for alignment equal to alignof(max_align_t). We can’t enable this fix unconditionally without breaking ABI since doing so changes layout of types with members whose type is a highly-aligned specialization of aligned_storage. As an interim solution until a future ABI-breaking release, compilation of programs that use highly-aligned aligned_storage produces a compile error explaining this issue and asking the user to define either _ENABLE_EXTENDED_ALIGNED_STORAGE to request the conforming-but-potentially-ABI-breaking behavior, or _DISABLE_EXTENDED_ALIGNED_STORAGE to request the previous incorrect-but-ABI-safe behavior.
Performance and Throughput Improvements
  • Fixed iterator wrappers like move_iterator and reverse_iterator defeating iterator debugging optimizations. These wrappers remained “checked” even after verified by algorithms. For example, fill(someVectorOfInt.rbegin(), someVectorOfInt.rend()) will properly check the range and convert to reverse_iterator<int *> instead of staying a reverse_iterator<vector::iterator> as in previous releases.
  • Changed several calls of basic_string::append(1, ch) to basic_string::push_back for micro-perf improvements in iostreams machinery.
  • Implemented a fast path for binary I/O in iostreams, quadrupling bulk I/O performance.
Other Changes
  • Removed _NOEXCEPT and other internal non-Standard macros.
  • Increased readability by consistently using nullptr in the STL’s headers.

If you have any feedback or suggestions for us, let us know. We can be reached via the comments below, via email (visualcpp@microsoft.com) and you can provide feedback via Help > Report A Problem in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

Chat with the Visual C++ Team at CppCon 2018

$
0
0

We are super excited to be returning to CppCon in Bellevue this year! We will have a table Monday – Friday where you can meet us and talk with us about Visual Studio, Visual Studio Code, and vcpkg. Additionally, we’d like to invite to you several sessions that folks from our team will be presenting this year:  

Monday, September 24th
14:00 – 15:00
How to Write Well-Behaved Value Wrappers by Simon Brand  

15:15 – 16:15
How C++ Debuggers Work by Simon Brand  

Tuesday, September 25th
14:00 – 15:00
What Could Possibly Go Wrong?: A Tale of Expectations and Exceptions by Simon Brand and Phil Nash  

15:15 – 15:45
Overloading: The Bane of All Higher-Order Functions by Simon Brand  

20:30
Tool Time – Come talk to team members from Visual Studio, Visual Studio Code, and vcpkg  

Wednesday, September 26th
12:30 – 13:30
C++ Community Building Birds of a Feather with Stephan T. Lavavej and others  

14:00 – 15:00
Latest and Greatest in the Visual Studio Family for C++ Developers 2018 by Marian Luparu and Steve Carroll  

15:15 – 15:45
Don’t Package Your Libraries, Write Packagable Libraries! by Robert Schumacher
What’s new in Visual Studio Code for C++ Development by Rong Lu  

15:50 – 16:20
Value Semantics: Fast, Safe, and Correct by Default by Nicole Mazzuca  

16:45 – 17:45
Memory Latency Troubles You? Nano-coroutines to the Rescue! (Using Coroutines TS, of Course) by Gor Nishanov  

18:45 – 20:00
Cross-Platform C++ Development is Challenging – let Tools Help! by Marc Goodner and Will Buik  

Thursday, September 27th
9:00 – 10:00
Inside Visual C++’s Parallel Algorithms by Billy O’Neal  

15:15 – 15:45
ConcurrencyCheck – Static Analyzer for Concurrency Issues in Modern C++ by Anna Gringauze  

16:45 – 17:45
Class Template Argument Deduction for Everyone by Stephan T. Lavavej  

Swing by our Exhibitor Table 

Find us at our Exhibitor Table to ask us all your questions, snag a shiny new sticker for your laptop, and grab a sweet t-shirt. Make sure you also fill out our survey for a chance to win an Xbox One S! Follow us on Twitter @visualc to stay up-to-date with the latest news.

cppcon-2018-sweepstakes-official-rules

$
0
0

MICROSOFT CLOUD AND ENTERPRISE CPPCON EVENT SWEEPSTAKES

OFFICIAL RULES

NO PURCHASE NECESSARY. 

PLEASE NOTE: It is your sole responsibility to comply with your employer’s gift policies.  If your participation violates your employer’s policies, you may be disqualified. Microsoft disclaims any and all liability and will not be party to any disputes or actions related to this matter.

GOVERNMENT EMPLOYEES: Microsoft is committed to complying with government gift and ethics rules and therefore government employees are not eligible.

WHAT ARE THE START AND END DATES?

This Sweepstakes starts on September 22, 2018, and ends on September 27, 2018 (“Entry Period”) and will be conducted during regular event hours. Winners will be selected Thursday morning, September 27, before the 10:30am session.

Entries must be received within the Entry Period to be eligible.

CAN I ENTER?

You are eligible to enter if you meet the following requirements at time entry:

·       You are a registered attendee of CppCon and you are 18 years of age or older; and

·       If you are 18 of age or older, but are considered a minor in your place of residence, you should ask your parent’s or legal guardian’s permission prior to submitting an entry into this Sweepstakes; and

 You are NOT a resident of any of the following countries: Cuba, Iran, North Korea, Sudan, and Syria.

·       PLEASE NOTE: U.S. export regulations prohibit the export of goods and services to Cuba, Iran, North Korea, Sudan and Syria. Therefore residents of these countries / regions are not eligible to participate.

 You are NOT event exhibitor support personnel; and

·       You are NOT an employee of Microsoft Corporation, or an employee of a Microsoft subsidiary; and

·       You are NOT an immediate family (parent, sibling, spouse, child) or household member of a Microsoft employee, an employee of a Microsoft subsidiary, any person involved in any part of the administration and execution of this Sweepstakes.

This Sweepstakes is void where prohibited by law.

HOW DO I ENTER?

You can enter by completing a short survey, http://aka.ms/cppcon.  All required survey questions must be answered to receive an entry.

We will only accept one (1) entry(ies) per entrant. We are not responsible for entries that we do not receive for any reason, or for entries that we receive but are not decipherable for any reason.

We will automatically disqualify:

·       Any incomplete or illegible entry; and

·       Any entries that we receive from you that are in excess of the entry limit described above.

WINNER SELECTION AND PRIZES

At the close of the event, we will randomly select winners of the prizes designated below.

One (1) Grand Prize(s).  A(n) Microsoft Xbox One S – Starter Bundle – game console – 1 TB HDD – white.  Approximate Retail Value (ARV) $299.00.

The ARV of electronic prizes is subject to price fluctuations in the consumer marketplace based on, among other things, any gap in time between the date the ARV is estimated for purposes of these Official Rules and the date the prize is awarded or redeemed.  We will determine the value of the prize to be the fair market value at the time of prize award.

The total Approximate Retail Value (ARV) of all prizes: $299

We will only award one (1) prize(s) per person during the Entry Period.

WINNER NOTIFICATION

Winners will be selected randomly and must be present at time of drawing to win.

GENERAL CONDITIONS

Taxes on the prize, if any, are the sole responsibility of the winner.  All federal, state, and local laws and regulations apply.  No substitution, transfer, or assignment of prize permitted, except that Microsoft reserves the right to substitute a prize of equal or greater value in the event the offered prize is unavailable. Prize winners may be required to sign and return an Affidavit of Eligibility and Liability Release and W-9 tax  form or W-8 BEN tax form within 10 days of notification. If you complete a tax form, you will be issued an IRS 1099 the following January, for the actual value of the prize. You are advised to seek independent counsel regarding the tax implications of accepting a prize. If a selected winner cannot be contacted, is ineligible, fails to claim a prize or fails to return the Affidavit of Eligibility and Liability Release or W-8 BEN form, the selected winner will forfeit their prize and an alternate winner will be selected. Your odds of winning depend on the number of eligible entries we receive. In the event of a dispute all decisions of Microsoft are final.

By entering this Sweepstakes you agree:

·       To abide by these Official Rules; and

·       To release and hold harmless Microsoft and its respective parents, subsidiaries, affiliates, employees and agents from any and all liability or any injury, loss or damage of any kind arising from or in connection with this Sweepstakes or any prize won; and

·       That by accepting a prize, Microsoft may use of your proper name and state of residence online and in print, or in any other media, in connection with this Sweepstakes, without payment or compensation to you, except where prohibited by law.

WHAT IF SOMETHING UNEXPECTED HAPPENS AND THE SWEEPSTAKES CAN’T RUN AS PLANNED?

If someone cheats, or a virus, bug, bot, catastrophic event, or any other unforeseen or unexpected event that cannot be reasonably anticipated or controlled, (also referred to as force majeure) affects the fairness and / or integrity of this Sweepstakes, we reserve the right to cancel, change or suspend this Sweepstakes.  This right is reserved whether the event is due to human or technical error. If a solution cannot be found to restore the integrity of the Sweepstakes, we reserve the right to select winners from among all eligible entries received before we had to cancel, change or suspend the Sweepstakes.

If you attempt or we have strong reason to believe that you have compromised the integrity or the legitimate operation of this Sweepstakes by cheating, hacking, creating a bot or other automated program, or by committing fraud in ANY way, we may seek damages from you to the fullest extent permitted by law.  Further, we may disqualify you, and ban you from participating in any of our future Sweepstakes, so please play fairly.

WINNERS LIST AND SPONSOR

If you send an email to visualcpp@microsoft.com within 30 days of winner selection, we will provide you with a list of winners that receive a prize worth $25.00 or more.

This Sweepstakes is sponsored by Microsoft Corporation, One Microsoft Way, Redmond, WA 98052.

PRIVACY STATEMENT

At Microsoft, we are committed to protecting your privacy.  Microsoft uses the information you provide to notify prize winners, and to send you information about other Microsoft products and services, if requested by you.  Microsoft will not share the information you provide with third parties without your permission except where necessary to complete the services or transactions you have requested, or as required by law.  Microsoft is committed to protecting the security of your personal information.  We use a variety of security technologies and procedures to help protect your personal information from unauthorized access, use, or disclosure. Your personal information is never shared outside the company without your permission, except under conditions explained above.

If you believe that Microsoft has not adhered to this statement, please notify us by sending email to visualcpp@microsoft.com or postal mail to visualcpp@microsoft.com, Microsoft Privacy, Microsoft Corporation, One Microsoft Way, Redmond, WA 98052 USA, and we will use commercially reasonable efforts to remedy the situation.


std::string_view: The Duct Tape of String Types

$
0
0

Visual Studio 2017 contains support for std::string_view, a type added in C++17 to serve some of the roles previously served by const char * and const std::string& parameters. string_view is neither a “better const std::string&”, nor “better const char *”; it is neither a superset or subset of either. std::string_view is intended to be a kind of universal “glue” — a type describing the minimum common interface necessary to read string data. It doesn’t require that the data be null-terminated, and doesn’t place any restrictions on the data’s lifetime. This gives you type erasure for “free”, as a function accepting a string_view can be made to work with any string-like type, without making the function into a template, or constraining the interface of that function to a particular subset of string types.

tl;dr

string_view solves the “every platform and library has its own string type” problem for parameters. It can bind to any sequence of characters, so you can just write your function as accepting a string view:

void f(wstring_view); // string_view that uses wchar_t's

and call it without caring what stringlike type the calling code is using (and for (char*, length) argument pairs just add {} around them)

// pass a std::wstring:
std::wstring& s;         f(s);

// pass a C-style null-terminated string (string_view is not null-terminated):
wchar_t* ns = "";        f(ns);

// pass a C-style character array of len characters (excluding null terminator):
wchar_t* cs, size_t len; f({cs,len});

// pass a WinRT string
winrt::hstring hs;       f(hs);

f is just an ordinary function, it doesn’t have to be a template.

string_view as a Generic String Parameter

Today, the most common “lowest common denominator” used to pass string data around is the null-terminated string (or as the standard calls it, the Null-Terminated Character Type Sequence). This has been with us since long before C++, and provides clean “flat C” interoperability. However, char* and its support library are associated with exploitable code, because length information is an in-band property of the data and susceptible to tampering. Moreover, the null used to delimit the length prohibits embedded nulls and causes one of the most common string operations, asking for the length, to be linear in the length of the string.

Sometimes const std::string& can be used to pass string data and erase the source, because it accepts std::string objects, const char * pointers, and string literals like “meow”. Unfortunately, const std::string& creates “impedance mismatches” when interacting with code that uses other string types. If you want to talk to COM, you need to use BSTR. If you want to talk to WinRT, you need HSTRING. For NT, UNICODE_STRING, and so on. Each programming domain makes up their own new string type, lifetime semantics, and interface, but a lot of text processing code out there doesn’t care about that. Allocating entire copies of the data to process just to make differing string types happy is suboptimal for performance and reliability.

Example: A Function Accepting std::wstring and winrt::hstring

Consider the following program. It has a library function compiled in a separate .cpp, which doesn’t handle all string types explicitly but still works with any string type.

// library.cpp
#include <stddef.h>
#include <string_view>
#include <algorithm>

size_t count_letter_Rs(std::wstring_view sv) noexcept {
    return std::count(sv.begin(), sv.end(), L'R');
}
// program.cpp
// compile with: cl /std:c++17 /EHsc /W4 /WX
//    /I"%WindowsSdkDir%Include\%UCRTVersion%\cppwinrt" .\program.cpp .\library.cpp
#include <stddef.h>
#include <string.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>

#pragma comment(lib, "windowsapp")
#include <winrt/base.h>

// Library function, the .cpp caller doesn't need to know the implementation
size_t count_letter_Rs(std::wstring_view) noexcept;

int main() {
    std::wstring exampleWString(L"Hello wstring world!");
    exampleWString.push_back(L'\0');
    exampleWString.append(L"ARRRR embedded nulls");
    winrt::hstring exampleHString(L"Hello HSTRING world!");

    // Performance and reliability is improved vs. passing std::wstring, as
    // the following conversions don't allocate and can't fail:
    static_assert(noexcept(std::wstring_view{exampleWString}));
    static_assert(noexcept(std::wstring_view{exampleHString}));

    std::wcout << L"Rs in " << exampleWString
        << L": " << count_letter_Rs(exampleWString) << L"\n";

    // note HStringWrapper->wstring_view implicit conversion when calling
    // count_letter_Rs
    std::wcout << L"Rs in " << std::wstring_view{exampleHString}
        << L": " << count_letter_Rs(exampleHString) << L"\n";
}

Output:

>.\program.exe
Rs in Hello wstring world! ARRRR embedded nulls: 4
Rs in Hello HSTRING world!: 1

The preceding example demonstrates a number of desirable properties of string_view (or wstring_view in this case):

vs. making count_letter_Rs some kind of template
Compile time and code size is reduced because only one instance of count_letter_Rs need be compiled. The interface of the string types in use need not be uniform, allowing types like winrt::hstring, MFC CString, or QString to work as long as a suitable conversion function is added to the string type.
vs. const char *
By accepting string_view, count_letter_Rs need not do a strlen or wcslen on the input. Embedded nulls work without problems, and there’s no chance of in-band null manipulation errors introducing bugs.
vs. const std::string&
As described in the comment above, string_view avoids a separate allocation and potential failure mode, because it passes a pointer to the string’s data, rather than making an entire owned copy of that data.
string_view For Parsers

Another place where non-allocating non-owning string pieces exposed as string_view can be useful is in parsing applications. For example, the C++17 std::filesystem::path implementation that comes with Visual C++ uses std::wstring_view internally when parsing and decomposing paths. The resulting string_views can be returned directly from functions like std::filesystem::path::filename(), but functions like std::filesystem::path::has_filename() which don’t actually need to make copies are natural to write.

inline wstring_view parse_filename(const wstring_view text)
	{	// attempt to parse text as a path and return the filename if it exists; otherwise,
		// an empty view
	const auto first = text.data();
	const auto last = first + text.size();
	const auto filename = find_filename(first, last); // algorithm defined elsewhere
	return wstring_view(filename, last - filename);
	}

class path
	{
public:
	// [...]
	path filename() const
		{	// parse the filename from *this and return a copy if present; otherwise,
			// return the empty path
		return parse_filename(native());
		}
	bool has_filename() const noexcept
		{	// parse the filename from *this and return whether it exists
		return !parse_filename(native()).empty();
		}
	// [...]
	};

In the std::experimental::filesystem implementation written before string_view, path::filename() contains the parsing logic, and returns a std::experimental::filesystem::path. has_filename is implemented in terms of filename, as depicted in the standard, allocating a path to immediately throw it away.

Iterator Debugging Support

In debugging builds, MSVC’s string_view implementation is instrumented to detect many kinds of buffer management errors. The valid input range is stamped into string_view’s iterators when they are constructed, and unsafe iterator operations are blocked with a message describing what the problem was.

// compile with cl /EHsc /W4 /WX /std:c++17 /MDd .\program.cpp
#include <crtdbg.h>
#include <string_view>

int main() {
    // The next 3 lines cause assertion failures to go to stdout instead of popping a dialog:
    _set_abort_behavior(0, _WRITE_ABORT_MSG);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);

    // Do something bad with a string_view iterator:
    std::string_view test_me("hello world");
    (void)(test_me.begin() + 100); // dies
}
>cl /nologo /MDd /EHsc /W4 /WX /std:c++17 .\test.cpp
test.cpp

>.\test.exe
xstring(439) : Assertion failed: cannot seek string_view iterator after end

Now, this example might seem a bit obvious, because we’re clearly incrementing the iterator further than the input allows, but catching mistakes like this can make debugging much easier in something more complex. For example, a function expecting to move an iterator to the next ‘)’:

// compile with cl /EHsc /W4 /WX /std:c++17 /MDd .\program.cpp
#include <crtdbg.h>
#include <string_view>

using std::string_view;

string_view::iterator find_end_paren(string_view::iterator it) noexcept {
    while (*it != ')') {
        ++it;
    }

    return it;
}

int main() {
    _set_abort_behavior(0, _WRITE_ABORT_MSG);
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
    string_view example{"malformed input"};
    const auto result = find_end_paren(example.begin());
    (void)result;
}
>cl /nologo /EHsc /W4 /WX /std:c++17 /MDd .\program.cpp
program.cpp

>.\program.exe
xstring(358) : Assertion failed: cannot dereference end string_view iterator
Pitfall #1: std::string_view doesn’t own its data, or extend lifetime

Because string_view doesn’t own its actual buffer, it’s easy to write code that assumes data will live a long time. An easy way to demonstrate this problem is to have a string_view data member. For example, a struct like the following is dangerous:

struct X {
    std::string_view sv; // Danger!
    explicit X(std::string_view sv_) : sv(sv_) {}
};

because a caller can expect to do something like:

int main() {
    std::string hello{"hello"};
    X example{hello + " world"}; // forms string_view to string destroyed at the semicolon
    putc(example.sv[0]); // undefined behavior
}

In this example, the expression `hello + ” world”` creates a temporary std::string, which is converted to a std::string_view before the constructor of X is called. X stores a string_view to that temporary string, and that temporary string is destroyed at the end of the full expression constructing `example`. At this point, it would be no different if X had tried to store a const char * which was deallocated. X really wants to extend the lifetime of the string data here, so it must make an actual copy.

There are of course conditions where a string_view member is fine; if you’re implementing a parser and are describing a data structure tied to the input, this may be OK, as std::regex does with std::sub_match. Just be aware that string_view’s lifetime semantics are more like that of a pointer.

Pitfall #2: Type Deduction and Implicit Conversions

Attempting to generalize functions to different character types by accepting basic_string_view instead of string_view or wstring_view prevents the intended use of implicit conversion. If we modify the program from earlier to accept a template instead of wstring_view, the example no longer works.

// program.cpp
// compile with: cl /std:c++17 /EHsc /W4 /WX
//    /I"%WindowsSdkDir%Include\%UCRTVersion%\cppwinrt" .\program.cpp
#include <stddef.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <locale>
#include <stdexcept>
#include <string>
#include <string_view>

#pragma comment(lib, "windowsapp")
#include <winrt/base.h>

template<class Char>
size_t count_letter_Rs(std::basic_string_view<Char> sv) noexcept {
    return std::count(sv.begin(), sv.end(),
        std::use_facet<std::ctype<Char>>(std::locale()).widen('R'));
}

int main() {
    std::wstring exampleWString(L"Hello wstring world!");
    winrt::hstring exampleHString(L"Hello HSTRING world!");
    count_letter_Rs(exampleWString); // no longer compiles; can't deduce Char
    count_letter_Rs(std::wstring_view{exampleWString}); // OK
    count_letter_Rs(exampleHString); // also no longer compiles; can't deduce Char
    count_letter_Rs(std::wstring_view{exampleHString}); // OK
}

In this example, we want exampleWString to be implicitly converted to a basic_string_view<wchar_t>. However, for that to happen we need template argument deduction to deduce CharT == wchar_t, so that we get count_letter_Rs. Template argument deduction runs before overload resolution or attempting to find conversion sequences, so it has no idea that basic_string is at all related to basic_string_view, and type deduction fails, and the program does not compile. As a result, prefer accepting a specialization of basic_string_view like string_view or wstring_view rather than a templatized basic_string_view in your interfaces.

In Closing

We hope string_view will serve as an interoperability bridge to allow more C++ code to seamlessly communicate. We are always interested in your feedback. Should you encounter issues please let us know through Help > Report A Problem in the product, or via Developer Community. Let us know your suggestions through UserVoice. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

Books on C++17

$
0
0

This post is part of a regular series of posts where the C++ product team here at Microsoft and other guests answer questions we have received from customers. The questions can be about anything C++ related: MSVC toolset, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc. Today’s post is by Marian Luparu.

C++17 is an important evolution of the C++ language, and you may be wondering how you should get started learning about it. On our blog, you will always find the latest announcements related to our team’s work on C++17 and future standards and, as part of this new series, advice on any C++17 related topics you’ve asked us about. But many of you may also want the more systematic approach to learning, an approach that books can give you when absorbing such a large topic.

Here are three books, written by our Microsoft MVPs, that can be good starting points to get yourself familiar with C++17

Professional C++, 4th edition, by Marc Gregoire

“Professional C++” is the advanced manual for C++ programming. Designed to help experienced developers get more out of the latest release, this book skims over the basics and dives right in to exploiting the full capabilities of C++17. Each feature is explained by example, each including actual code snippets that you can plug into your own applications. Case studies include extensive, working code that has been tested on Windows and Linux, and the author’s expert tips, tricks, and workarounds can dramatically enhance your workflow. Even many experienced developers have never fully explored the boundaries of the language’s capabilities; this book reveals the advanced features you never knew about, and drills down to show you how to turn these features into real-world solutions.

C++ is notoriously complex, and whether you use it for gaming or business, maximizing its functionality means keeping up to date with the latest changes. Whether these changes enhance your work or make it harder depends on how well-versed you are in the newest C++ features. Professional C++ gets you up to date quickly, and provides the answers you need for everyday solutions.

The Modern C++ Challenge: Become an expert programmer by solving real-world problems, by Marius Bancila

C++ is one of the most widely-used programming languages and has applications in a variety of fields, such as gaming, GUI programming, and operating systems, to name a few. Through the years, C++ has evolved into (and remains) one of the top choices for software developers worldwide. This book will show you some notable C++ features and how to implement them to meet your application needs. Each problem is unique and doesn’t just test your knowledge of the language; it tests your ability to think out of the box and come up with the best solutions. With varying levels of difficulty, you’ll be faced with a wide variety of challenges. And in case you’re stumped, you don’t have to worry: we’ve got the best solutions to the problems in the book. So are you up for the challenge?

This book will appeal to C++ developers of all levels. There’s a challenge inside for everyone.

C++17 in Detail, by Bartłomiej Filipek

Although C++17 is not as big as C++11, it’s larger than C++14. Everyone expected modules, co-routines, concepts and other powerful features, but it wasn’t possible to prepare everything on time. Is C++17 weak? Far from it! And this book will show you why!

The book brings you exclusive content about C++17 and draws from the experience of many articles that have appeared on bfilipek.com. The chapters were rewritten from the ground-up and updated with the latest information. All of that equipped with lots of new examples and practical tips. Additionally, the book provides insight into the current implementation status, compiler support, performance issues and other relevant knowledge to boost your current projects.

If you know a bit of C++11/14 and you want to move forward into the latest C++ techniques, then this book is for you.

What other good C++17 books would you recommend to someone that is just getting started with C++? How about a C++ expert that hasn’t looked at C++17 yet?

Step Back – Going Back in C++ Time

$
0
0

Step Back for C++

In the most recent, 15.9, update to Visual Studio 2017 Enterprise Edition, we’ve added “Step Back” for C++ developers targeting Windows 10 Anniversary Update (1607) and later. With this feature, you can now return to a previous state while debugging without having to restart the entire process. It’s installed as part of the C++ workload but set to “off” by default. To enable it, go to Tools -> Options -> IntelliTrace and select the “IntelliTrace snapshots” option. This will enable snapshots for both Managed and Native code.

Once “Step Back” is enabled, you will see snapshots appear in the Events tab of the Diagnostic Tools Window when you are stepping through C++ code.

Clicking on any event will take you back to its respective snapshot – which is a much more productive way to go back in time if you want to go further back than a few steps. Or, you can simply use the Step Backward button on the debug command bar to go back in time. You can see “Step Back” in action in concurrence with “Step Over” in the gif below.

Under the Hood

So far, we’ve talked about “Step Back” and how you can enable and use it in Visual Studio, but you could have read that on the VS blog. Here on the VC++ blog, I thought it would be interesting to explain how the feature works and what the trade offs are. After all, no software, debuggers included, are magical!

At the core of “Step Back” is an API in Windows called PssCaptureSnapshot (docs). While the API isn’t very descriptive, there are two key things that it does to a process. Given a target process it will:

  1. Create a ‘snapshot’ which looks suspiciously like the child process of an existing process that has no threads running.
  2. Mark the processes memory, it’s page tables (Wikipedia), as copy-on-write (Wikipedia). That means that whenever a table is written to, the table is copied.

The important thing about the above is that between the two you basically get a copy of the entire virtual memory space used by the process that you snapshotted. From inside that process you can then inspect the state, the memory, of the application as it was at the time the snapshot was created. This is handy for the feature which the API was originally designed for; the serialization of a process at the point of failure .

In VS when debugging C++, we take these snapshots on certain debugger events, namely:

  1. When a breakpoint is hit
  2. When a step event occurs – but only if the time between the stepping action and the previous stepping action is above a certain threshold (around ~300ms). This helps with the case where you are hammering the stepping buttons and just want to step at all possible speed.

From a practical perspective, that means there will be a snapshot as you step through code. We keep a First in First Out buffer of snapshots, freeing them up as more are taken. One of the downsides of this approach, is that we aren’t taking snapshots as your app is running so you can’t hit a breakpoint and then go back to see what happened before the breakpoint was hit.

Now there is a copy of the process, a snapshot, but how does that get debugged in VS?

Well, this is the ‘easy’ bit, basically when you hit “Step Back” or activate a snapshot from the Diagnostic Tools window, VS goes ahead and attaches the debugger to that process. We hide this from you in the VS UI, so it still looks like you are debugging the process you started with, but in reality, you are debugging the snapshot process with all the state from the past. Once you go back to ‘live’ debugging you will back to the main process which is still paused at the location you left it.

Performance of Step Back

One of the first considerations of adding any new feature to the debugger is on how it might impact the performance of VS while debugging. While improving performance of VS is something of a Sisyphean task and as many improvements as we make there is more to be made as well as additional features that take some of those wins. Taking a snapshot takes time, everything does, in this case it takes time both in the process being debugged and back in VS. There’s no sure way to predict how long it will take as it’s dependent on the app and how it’s using memory, but while we don’t have a magic 8 ball, we do have data, lots of it…

As of the time of writing, from testing and dogfooding usage in the last 28 days use we’ve seen 29,635,121 snapshots taken across 14,738 machines. From that data set we can see that the 75th percentile for how long it took to take a snapshot is 81ms. You can see a more detailed breakdown in the graph below.


In any case, if you were wondering why “Step Back” isn’t on by default, that graph above is why, “Step Back” simply impacts stepping performance too much to be on by default, all the time, for everyone. Instead, it’s a tool that you should decide to use and, by and large, you’ll likely never notice the impact. Though, if you did we will turn off “Step Back” and show a ‘gold bar’ notification that we’ve done so. The ‘gold bars’ are the notifications that pop at the top of the editor, the picture below shows the one for when you try “Step Back” without snapshots being enabled.
That’s the CPU usage aspect of performance out the way, now to look at the second aspect, memory.

As you continue to debug your app and the app continues execution it will no doubt write to memory. This could be to set a value from 1 to 2 as in the example above. Or it could be something more complex, but in any case, when it comes time to write that change the OS is going to copy the associated page table to a new location. Duplicating the data that was changed, and potential other data, at the new location, while keeping the old. That new location will continue to be used. That means that the old location still has the old value, 1, from the time the snapshot was taken, and the new location has the value of 2. As Windows is now copying memory as it’s written, the app will consume more memory. How much though depends on the application and what it’s doing. The consumption of memory is directly proportional to how volatile it is. For example, in the trivial app above each step is going to consume a tiny bit more data. But, if the app instead were encoding an image or doing something intense a lot more memory would get consumed than would be typical.

Now as memory, even virtual, is finite this poses some limitations on step back. Namely that we can’t keep an infinite number of snapshots around. At some point we have to free them and their associated memory up. We do that in two ways; firstly, the snapshots are let go on a First in First out basis once a limit of a 100 has been reached. That is, you can never step back more than a 100x. That cap is arbitrary though, a magic number. There’s an additional cap that’s enforced and based on heuristics, essentially VS is watching memory usage and in the event of low memory snapshots get dropped starting with the oldest – just as if a 100 was hit.

Conclusion

We’ve covered how you can use “Step Back” and how it works under the hood and hopefully you are now in a place to make an informed decision on when to use the feature. While this feature is only in the Enterprise versions of Visual Studio you can always try out the preview channel of Visual Studio Enterprise. I highly recommend you go turn it on, for me, personally it’s saved a whole bunch of time not restarting a debug session. And when you do use the feature I’d love to hear your feedback, and as ever if you have any feedback on the debugger experience in VS let us know!

You can also reach me by mail at andster@microsoft.com)or on twitter at https://twitter.com/andysterland.

Thanks for reading!

Andy Sterland

Program Manager, Visual Studio, Diagnostics Team

CUDA 10 is now available, with support for the latest Visual Studio 2017 versions

$
0
0

We are pleased to echo NVIDIA announcement for CUDA 10 today, and particularly excited about CUDA 10.0’s Visual Studio compatibility. CUDA 10.0 will work with all the past and future updates of Visual Studio 2017. To stay committed to our promise for a Pain-free upgrade to any version of Visual Studio 2017, we partnered closely with NVIDIA for the past few months to make sure CUDA users can easily migrate between Visual Studio versions. Congratulations to NVIDIA for this milestone and thank you for a great collaboration!

A Bit of Background

In various updates of Visual Studio 2017 (e.g. 15.5) and even earlier major Visual Studio versions, we discovered that some of the library headers became incompatible with CUDA’s NVCC compiler in 9.x versions. The crux of the problem is about two C++ compilers adding modern C++ standard features at different paces but having to work with a common set of C++ headers (e.g. STL headers). We heard from many of you that this issue is forcing you to stay behind on older versions of Visual Studio. Thank you for that feedback. Together with NVIDIA, we now have a solution that will enable all Visual Studio 2017 update versions to work with CUDA 10.0 tools. This is also reinforced by both sides adding tests and validation processes as part of release quality gates. For example, we now have added (NVIDIA/Cutlass), a CUDA C++ project, into the MSVC Real-World Testing repository as a requirement for shipping. We also have targeted unit tests for PR build validations to guard against potential incompatibility issues.

In closing

We’d love for you to download Visual Studio 2017 version 15.8 and try out all the new C++ features and improvements. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter other problems with MSVC in Visual Studio 2017 please let us know through Help > Report A Problem in the product, or via Developer Community. Let us know your suggestions through UserVoice. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

std::any: How, when, and why

$
0
0

This post is part of a regular series of posts where the C++ product team here at Microsoft and other guests answer questions we have received from customers. The questions can be about anything C++ related: MSVC toolset, the standard language and library, the C++ standards committee, isocpp.org, CppCon, etc. Today’s post is by Casey Carter.

C++17 adds several new “vocabulary types” – types intended to be used in the interfaces between components from different sources – to the standard library. MSVC has been shipping implementations of std::optionalstd::any, and std::variantsince the Visual Studio 2017 release, but we haven’t provided any guidelines on how and when these vocabulary types should be used. This article on std::any is the second of a series that examines each of the vocabulary types in turn.

Storing arbitrary user data

Say you’re creating a calendar component that you intend to distribute in a library for use by other programmers. You want your calendar to be usable for solving a wide array of problems, so you decide you need a mechanism to associate arbitrary client data with days/weeks/months/years. How do you best implement this extensibility design requirement?

A C programmer might add a void* to each appropriate data structure:

struct day { 
  // ...things... 
  void* user_data; 
}; 

struct month { 
  std::vector<day> days; 
  void* user_data; 
};

and suggest that clients hang whatever data they like from it. This solution has a few immediately apparent shortcomings:

  • You can always cast a void* to a Foo* whether or not the object it points at is actually a Foo. The lack of type information for the associated data means that the library can’t provide even a basic level of type safety by guaranteeing that later accesses to stored data use the same type as was stored originally:
    some_day.user_data = new std::string{"Hello, World!"}; 
    // …much later 
    Foo* some_foo = static_cast<Foo*>(some_day.user_data); 
    some_foo->frobnicate(); // BOOM!
    
  • void* doesn’t manage lifetime like a smart pointer would, so clients must manage the lifetime of the associated data manually. Mistakes result in memory leaks:
    delete some_day.user_data; 
    some_day.user_data = nullptr; 
    some_month.days.clear(); // Oops: hopefully none of these days had 
                             // non-null user_data
    
  • The library cannot copy the object that a void* points at since it doesn’t know that object’s type. For example, if your library provides facilities to copy annotations from one week to another, clients must copy the associated data manually. As was the case with manual lifetime management, mistakes are likely to result in dangling pointers, double frees, or leaks:
    some_month.days[0] = some_month.days[1]; 
    if (some_month.days[1].user_data) { 
      // I'm storing strings in user_data, and don't want them shared 
      // between days. Copy manually: 
      std::string const& src = *some_month.days[1].user_data; 
      some_month.days[0].user_data = new std::string(src); 
    }
    

The C++ Standard Library provides us with at least one tool that can help: shared_ptr<void>. Replacing the void* with shared_ptr<void> solves the problem of lifetime management:

struct day {
  // ...things...
  std::shared_ptr<void> user_data;
};

struct month {
  std::vector<day> days;
  std::shared_ptr<void> user_data;
};

since shared_ptr squirrels away enough type info to know how to properly destroy the object it points at. A client could create a shared_ptr<Foo>, and the deleter would continue to work just fine after converting to shared_ptr<void> for storage in the calendar:

some_day.user_data = std::make_shared<std::string>("Hello, world!");
// ...much later...
some_day = some_other_day; // the object at which some_day.user_data _was_
                           // pointing is freed automatically

This solution may help solve the copyability problem as well, if the client is happy to have multiple days/weeks/etc. hold copies of the same shared_ptr<void> – denoting a single object – rather than independent values. shared_ptr doesn’t help with the primary problem of type-safety, however. Just as with void*shared_ptr<void> provides no help tracking the proper type for associated data. Using a shared_ptr instead of a void* also makes it impossible for clients to “hack the system” to avoid memory allocation by reinterpreting integral values as void* and storing them directly; using shared_ptr forces us to allocate memory even for tiny objects like int.

Not just any solution will do

std::any is the smarter void*/shared_ptr<void>. You can initialize an any with a value of any copyable type:

std::any a0; 
std::any a1 = 42; 
std::any a2 = month{"October"};

Like shared_ptrany remembers how to destroy the contained value for you when the any object is destroyed. Unlike shared_ptrany also remembers how to copy the contained value and does so when the any object is copied:

std::any a3 = a0; // Copies the empty any from the previous snippet
std::any a4 = a1; // Copies the "int"-containing any
a4 = a0;          // copy assignment works, and properly destroys the old value

Unlike shared_ptrany knows what type it contains:

assert(!a0.has_value());            // a0 is still empty
assert(a1.type() == typeid(int));
assert(a2.type() == typeid(month));
assert(a4.type() == typeid(void));  // type() returns typeid(void) when empty

and uses that knowledge to ensure that when you access the contained value – for example, by obtaining a reference with any_cast – you access it with the correct type:

assert(std::any_cast<int&>(a1) == 42);             // succeeds
std::string str = std::any_cast<std::string&>(a1); // throws bad_any_cast since
                                                   // a1 holds int, not string
assert(std::any_cast<month&>(a2).days.size() == 0);
std::any_cast<month&>(a2).days.push_back(some_day);

If you want to avoid exceptions in a particular code sequence and you are uncertain what type an any contains, you can perform a combined type query and access with the pointer overload of any_cast:

if (auto ptr = std::any_cast<int>(&a1)) {
  assert(*ptr == 42); // runs since a1 contains an int, and succeeds
}
if (auto ptr = std::any_cast<std::string>(&a1)) {
  assert(false);      // never runs: any_cast returns nullptr since
                      // a1 doesn't contain a string
}

The C++ Standard encourages implementations to store small objects with non-throwing move constructors directly in the storage of the any object, avoiding the costs of dynamic allocation. This feature is best-effort and there’s no guaranteed threshold below which any is portably guaranteed not to allocate. In practice, the Visual C++ implementation uses a larger any that avoids allocation for object types with non-throwing moves up to a handful of pointers in size, whereas libc++ and libstdc++ allocate for objects that are two or more pointers in size (See https://godbolt.org/z/RQd_w5).

How to select a vocabulary type (aka “What if you know the type(s) to be stored?”)

If you have knowledge about the type(s) being stored – beyond the fact that the types being stored must be copyable – then std::any is probably not the proper tool: its flexibility has performance costs. If there is exactly one such type T, you should reach for std::optional. If the types to store will always be function objects with a particular signature – callbacks, for example – you want std::function. If you only need to store types from some set fixed at compile time, std::variant is a good choice; but let’s not get ahead of ourselves – that will be the next article.

Conclusions

When you need to store an object of an arbitrary type, pull std::any out of your toolbox. Be aware that there are probably more appropriate tools available when you do know something about the type to be stored.

If you have any questions (Get it? “any” questions?), please feel free to post in the comments below. You can also send any comments and suggestions directly to the author via e-mail at cacarter@microsoft.com, or Twitter @CoderCasey. Thank you!

Viewing all 1541 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>