Visual C ++: redirect an array as a pointer

I cut out some C ++ 11 code that could not be compiled on Visual Studio 2015, the following, which I think should compile (and do with clang and gcc):

#include <utility> void test(const char* x); int main() { const char x[] = "Hello world!"; test(std::forward<const char*>(x)); } 

I understand that forward is not needed here. This shrinks from much more complex code, which decomposes any arrays in the variational argument down to pointers and forwards everything. I'm sure you can find ways around this with the specialization of templates or SFINAE, but I would like to know if this is really C ++ before I go down this road. The compiler is Visual Studio 2015, and the problem can be recreated in this online MSVC compiler . Compilation Error:

 main.cpp(13): error C2665: 'std::forward': none of the 2 overloads could convert all the argument types c:\tools_root\cl\inc\type_traits(1238): note: could be '_Ty &&std::forward<const char*>(const char *&&) noexcept' with [ _Ty=const char * ] c:\tools_root\cl\inc\type_traits(1231): note: or '_Ty &&std::forward<const char*>(const char *&) noexcept' with [ _Ty=const char * ] main.cpp(13): note: while trying to match the argument list '(const char [13])' 

Update:

@ Jakk offered an example more than the following:

 void test(const char*&& x); int main() { const char x[] = "Hello world!"; test(x); } 

This gives a more informative error:

 main.cpp(7): error C2664: 'void test(const char *&&)': cannot convert argument 1 from 'const char [13]' to 'const char *&&' main.cpp(7): note: You cannot bind an lvalue to an rvalue reference 

Again, this compiles to gcc and clang. The compiler flags for Visual C ++ were /EHsc /nologo /W4 /c . @Crazy Eddie suggests that this could be due to the VC ++ extension for passing temporary data as links is not const.

+8
c ++ language-lawyer c ++ 11 compiler-errors visual-studio-2015
source share
3 answers

For me, it looks like an error in MSVC, where it tries to be smart with a pointer array and makes a mistake.

Expand the second example:

The compiler must initialize const char*&& from an lvalue of type const char[13] . To do this, 8.5.3 says that it creates a temporary type const char* and initializes it with const char[13] , and then binds the link to a temporary one.

Initializing a const char* from const char[13] involves a simple conversion between arrays and pointers, which gives the value const char* , which is then copied to a temporary one.

Thus, the conversion is well defined, despite what MSVC says.

In the first example, this is not test () causing the problem, but a call to std::forward . std::forward<const char*> has two overloads, and MSVC does not complain, and is not viable. Two forms:

 const char*&& std::forward(const char*&&); const char*&& std::forward(const char*&); 

One takes the lvalue link, one takes the rvalue link. When considering whether overloading is viable, the compiler must find the sequence of the conversion from const char[13] to a reference to const char* .

Since the lvalue reference is not const (it is a reference to a pointer to const char, the pointer itself is not const), the compiler cannot apply the conversion sequence described above. In fact, no conversion sequence is valid, since conversion from an array to a pointer requires a temporary one, but you cannot bind non-constant lvalue references to temporary ones. Thus, MSVC correctly rejects the lvalue form.

The rvalue form, however, as I set above, should be accepted, but the MSVC is incorrectly rejected.

+4
source share

I believe std::decay<const char []>::type is what you are looking for http://en.cppreference.com/w/cpp/types/decay

0
source share

I think it should compile, but why are you trying to use std::forward ?

Wrong solution just replace

 std::forward<const char*>(x) 

from:

 (const char*)x 

or for the general case, replace:

 std::forward<decay_t<decltype(x)>>(x) 

from:

 decay_t<decltype(x)>(x) 

Using std::forward doesn't seem to have any purpose here, you have an array, you want to decompose it into a pointer, so do it.

-one
source share

All Articles