1

Constructor

PixelPlane::PixelPlane(int& width, int& height, const std::string& label)

Whenever I initialize the object with the following arguments

PixelPlane pixel_plane(960, 540, "Title");

Visual Studio underlines the 960 argument and displays the message No instance of constructor "PixelPlane::PixelPlane matches the argument list. Argument types are: (int, int, const char[5]). I saw someone do something similar without errors https://www.youtube.com/watch?v=1nfuYMXjZsA. Have I done something wrong or have I just overlooked something?

SuperSim135
  • 135
  • 1
  • 10
  • 6
    The problem isn't the string, it's the `int`s. You can't pass an `int` literal to a function that takes a `int&`. – Fred Larson Nov 27 '19 at 21:10
  • To answer the title, a string literal is an array of constant characters (in C++). The compiler is correct. (In C, the elements do not have the `const` attribute but are practically constant because the behavior upon attempting to modify them is not defined by the standard.) – Eric Postpischil Nov 27 '19 at 21:11
  • @FredLarson Is there a better alternative? – SuperSim135 Nov 27 '19 at 21:13
  • 3
    Why are you passing them by reference? If you're intending to modify them, you can't do that to literals. If you're not, you don't need to pass them by reference. – Fred Larson Nov 27 '19 at 21:14
  • 1
    Minor point: I think you mistyped the error message. The type of `"Title"` is `const char[6]`, not `const char[5]`. There's an implied `'\0'` at the end of the string. – Pete Becker Nov 28 '19 at 14:28

2 Answers2

8

You are passing rvalues (960 and 540) as an argument to the constructor that takes int& references. This is forbidden. The only time you can bind a rvalue to a reference is when the reference is marked const, e.g. const int& (or when you have a forwarding reference; see also Scott Meyers' excellent post (just replace universal by forwarding, as that's how those references are now called in the C++ standard)).

std::string has an implicit conversion from const char* (ctor #5 in the link), to which the const char[5] type of label decays to, so the string part is OK.

BTW, do not pass fundamental types by const reference. It doesn't save anything, and may prevent optimization. Pass by const reference only when the objects to be passed are expensive to copy (or when you deal with template code, see @Mark's comment). In your case just pass them by value

PixelPlane::PixelPlane(int width, int height, const std::string& label)
vsoftco
  • 55,410
  • 12
  • 139
  • 252
3

This

PixelPlane::PixelPlane(int& width, int& height, const std::string& label)

is trying to say: "Pass me a reference to two integers, because I want to modify them"

Informally speaking, you cannot modify 960 or 540. That doesnt make sense. And because it doesnt make sense the language forbids you do pass 960 or 540 where a (non-const) reference is expected.

More formally, 960 and 540 are rvalues. They dont have names, they cannot be assigned to.

Solution: change the constructor to take const int& or even better just int (assuming the parameters are not modified).

Why does my compiler percieve a string to be a const char[]?

String literals arent std::strings. "Title" really is a const char[5] (see eg here).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • For the sake of completeness, do you have a source stating that string literals are const arrays? Everything I've seen so far says they're `const char *`, though experience has shown me it's an array. –  Nov 27 '19 at 21:31
  • @Chipster added a link. "The type of an unprefixed string literal is const char[N]" – 463035818_is_not_an_ai Nov 27 '19 at 21:33
  • @Chipster seems like everything you have seen so far was wrong ;) arrays are not pointers. However typically you write `const char * my_string = "Hello world"` because array can decay to pointers – 463035818_is_not_an_ai Nov 27 '19 at 21:34
  • Oh, I'm sure everything I've seen so far is wrong. It'd just be nice to see the right thing once in a while ;). I had already up-voted your answer anyway, because it was a good answer even without the link, but thanks for the link. –  Nov 27 '19 at 21:37
  • @Chipster didnt want to come across as arrogant. Actually I am at a complete loss when the topic is c-arrays, string literals being `const char[N]` is about everything I know for sure – 463035818_is_not_an_ai Nov 27 '19 at 21:42
  • 1
    @Chipster then nevermind, its just too easy to misunderstand or be misunderstood – 463035818_is_not_an_ai Nov 27 '19 at 21:48
  • A fun thing when arrays stay arrays (passing them by array reference): `template void f(T (&arr)[N]){std::cout << "I'm an array of " << N << " elements\n";}`, see [this](http://coliru.stacked-crooked.com/a/99d8fb44fb4355a3). – vsoftco Nov 27 '19 at 22:06