1

Consider this class:

template <typename t>
class Something
{
public:
    Something(t theValue) {mValue=theValue;}
    t mValue;
};

When I do this, everything is okay:

Something<float>* mSomething=new Something<float>(100);

HOWEVER, if I try to do this:

Something<float> mSomething(100);

I am declaring the above inside another class-- i.e.

class SomethingElse
{
public:
     Something<float> mSomething(100);
};

It tells me that anything I put inside the parenthesis is a syntax error.

What exactly is the necessary syntax here-- or is this some quirk of templates and thus not possible?

Fail code example here: https://wandbox.org/permlink/anaQz9uoWwV9HCW2

KiraHoneybee
  • 495
  • 3
  • 12
  • This is literally my code that's failing-- this is my minimally reproducible example. I'm using Visual Studio's compiler-- anyone know if this is a quirk of Visual Studio? Only diff is, I'm declaring the mSomething(100) in another class. – KiraHoneybee Jun 08 '22 at 22:05
  • And that was the secret sauce. Including the other class or the error message in the initial question would have gotten you an answer within seconds. – user4581301 Jun 08 '22 at 22:18
  • @KiraHoneybee That's why an actual [mre] that can simply be copy-pasted and tested is so important. Your question makes it seem like you have a problem specifically with templates, but actually it has nothing at all to do with `Something`. If you had tried to use `int mSomething(100);` exactly the same would have happened. – user17732522 Jun 08 '22 at 22:50

1 Answers1

0

You may not use such an initializer as a function call

class SomethingElse
{
public:
     Something<float> mSomething(100);
};

You need to use an equal or braced initializer. For example

class SomethingElse
{
public:
     Something<float> mSomething { 100 };
};

Here is a demonstration program.

template <typename t>
class Something
{
public:
    Something(t theValue) {mValue=theValue;}
    t mValue;
};

class SomethingElse
{
public:
     Something<float> mSomething{ 100 };
};

int main()
{
}

According to the C++ grammar

member-declarator:
    declarator virt-specifier-seqopt pure-specifieropt
    declarator brace-or-equal-initializeropt
    identifieropt attribute-specifier-seqopt: constant-expression

See the term brace-or-equal-initializer.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Vlad, can you describe a little bit WHY it has to work this way? This seems insane syntax. Is it not hitting the constructor at all, just initializing the members? – KiraHoneybee Jun 08 '22 at 22:13
  • @KiraHoneybee It is a restriction of C++ for class member initializations. – Vlad from Moscow Jun 08 '22 at 22:14
  • @KiraHoneybee It puzzles me as well. I THINK it's because the compiler's expecting a function declaration, but that doesn't seem to me to be a large problem, so there must be some sneakiness that you have to be a compiler developer or language lawyer to understand. – user4581301 Jun 08 '22 at 22:24
  • It might just be ideological as C++ tries to migrate away from using brackets `()` in variable definitions and the ambiguities they cause. For example `type variable();` doesn't make a default initialized variable, it declares function named `variable` that returns a `type`. See the [Most Vexing Parse](https://en.wikipedia.org/wiki/Most_vexing_parse) for how ugly this can get. Using braces `{}` makes all of this go away. – user4581301 Jun 08 '22 at 22:28