How to call this function template? - c++

struct Message1 {
int a;
int b;
};
template<class MSG_T> void RegisterMessageType() {
MSG_T t;
}
Message1 m;
RegisterMessageType<Message1>();
Error message:
error C2909: 'RegisterMessageType': explicit instantiation of function template
requires return type
error C4430: missing type specifier - int assumed.
Note: C++ does not support default-int
error C2768: 'RegisterMessageType' : illegal use of explicit template arguments
What is wrong? Thanks.
Sorry, edit again.
if i put
Message1 m;
RegisterMessageType<Message1>();
into main function, it (VS2010) can compile it Okay. But if i put it outside of main, above compiling error occurred.

In C++, expressions (such as calling a function) can only occur inside functions (or inside initialisers of variables). Just putting a call outside of a function is an error.

Related

Inline member initializer containing pointer to member

At work, I'm experimenting a bit to bring some reflection into our codebase. Basically what I want to achieve, is to capture a pointer to data-member inside the type of the data-member's initializer:
template<class Class, int Class::*dataMember>
struct Reflect
{
operator int() {return 0;}
};
class Foo
{
public:
int bar = Reflect<Foo, &Foo::bar>{};
};
Although clang 3.4.1 (http://gcc.godbolt.org/) and Intel C++ XE 14.0 are able to compile this piece of code, when using MSVC12 I get the following error message:
error C2065: 'bar' : undeclared identifier
error C2975: 'dataMember' : invalid template argument for 'Reflect', expected compile-time constant expression
Furthermore, gcc 4.9.2 also seems to have trouble with it: http://ideone.com/ZUVOMO.
So my questions are:
Is the above piece of code valid C++11?
If yes, are there any work arounds for the failing compilers?
What VC++ complains about is certainly not a problem; [basic.scope.pdecl]/1,6:
The point of declaration for a name is immediately after its complete
declarator (Clause 8) and before its initializer (if any), except as
noted below.[…]
After the point of declaration of a class member, the member name can
be looked up in the scope of its class.
This implies that the name lookup is fine. However, as pointed out by #hvd in the comments, there are certain ambiguities in the grammar of such constructs.
Presumably GCC parses the above line until the comma:
int bar = Reflect<Foo,
// at this point Reflect < Foo can be a perfectly fine relational-expression.
// stuff after the comma could be a declarator for a second member.
And bails out once the rest is encountered.
A workaround that makes GCC happy is
int bar = decltype( Reflect<Foo, &Foo::bar>{} )();
Demo. This does not help with VC++ though, which apparently confuses the point of declaration as indicated by the error message.
Thus moving the initializer into a constructor will work:
int bar;
Foo() : bar( Reflect<Foo, &Foo::bar>{} ) {}
// (also works for GCC)
... while providing an initializer at the declaration of bar cannot. Demo #2 on rextester.

function returning a struct in c++?

I am trying to implement a function that returns a struct, but when I compile, it always gives me error.
In my header file:
class AcquireSaveInfo
{
private:
typedef struct
{
double x,y,z;
}resolution;
public:
resolution AddResolutionInfo();
};
in my cpp file:
resolution AcquireSaveInfo::AddResolutionInfo()
{
resolution res;
res.x = 0;
return res;
}
The error messages:
>.\AcquireSaveInfo.cpp(200) : error C2143: syntax error : missing ';' before 'AcquireSaveInfo::AddResolutionInfo'
3>.\AcquireSaveInfo.cpp(200) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
3>.\AcquireSaveInfo.cpp(201) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
3>.\AcquireSaveInfo.cpp(201) : error C2556: 'int AcquireSaveInfo::AddResolutionInfo(void)' : overloaded function differs only by return type from 'AcquireSaveInfo::resolution AcquireSaveInfo::AddResolutionInfo(void)'
3> c:\devolpment\commands\acquisition\runsample\runsample\AcquireSaveInfo.h(39) : see declaration of 'AcquireSaveInfo::AddResolutionInfo'
3>.\AcquireSaveInfo.cpp(201) : error C2371: 'AcquireSaveInfo::AddResolutionInfo' : redefinition; different basic types
I am wondering what is the problem with this? Thanks.
At the point of the function definition resolution is not known.
To overcome this issue, you should add the full scope resolution to the return type.
AcquireSaveInfo::resolution AcquireSaveInfo::AddResolutionInfo()
{
...
}
Alternatively, if your compiler complies to the newest C++11 standard, you could use the trailing return type declaration, for which case the full scope resolution is not required.
auto AcquireSaveInfo::AddResolutionInfo() -> resolution
{
...
}
You should also note resolution is a private type, that means outside the scope of AcquireSaveInfo, it will not be possible to explicitly declare an object of that type to receive the return value of AddResolutionInfo. If, however, you are again using a compiler complying to the C++11 standard, you could still implicitly declare an object of type resolution using the auto keyword.
AcquireSaveInfo a;
auto r = a.AddResolutionInfo();
You need a semicolon at the end of AcquireSaveInfo, like so
class AcquireSaveInfo
{
private:
typedef struct
{
double x,y,z;
}resolution;
public:
resolution AddResolutionInfo();
};
You have the resolution structure declared as private. Thus, if you attempt to return it from a public function, you will get an error because you cannot access the struct. (Example)
You can get around this by either declaring the struct in the public section of the class, or declare it outside the class entirely. In most cases, the latter would be preferred to making it a sub-class.
You made three mistakes
The first is that you forgot to place a semicolon after the closing brace of the class definition.
The second is that you did not specify qualified name for the return type of the function.
And the third error is that the only way to use return value of the function is to use type specifier auto because type AcquireSaveInfo::resolution is private. If your compiler does not support this type specifier then there is no possibility to use the return value of the function.

What's actually going on in this AnonymousClass(variable) declaration?

Trying to compile:
class AnonymousClass
{
public:
AnonymousClass(int x)
{
}
};
int main()
{
int x;
AnonymousClass(x);
return 0;
}
generates errors from MSVC:
foo.cpp(13) : error C2371: 'x' : redefinition; different basic types
foo.cpp(12) : see declaration of 'x'
foo.cpp(13) : error C2512: 'AnonymousClass' : no appropriate default constructor available
g++'s error messages are similar:
foo.cpp: In function ‘int main()’:
foo.cpp:13: error: conflicting declaration ‘AnonymousClass x’
foo.cpp:12: error: ‘x’ has a previous declaration as ‘int x’
foo.cpp:12: warning: unused variable ‘x’
It's easily fixable by giving the AnonymousClass object an explicit name, but what's going on here and why? I presume that this is more declaration syntax weirdness (like the cases described in Q10.2 and Q10.21 of the comp.lang.C++ FAQ), but I'm not familiar with this one.
AnonymousClass(x);
It defines a variable x of type AnonymousClass. That is why you're getting redefinition error, because x is already declared as int.
The parentheses are superfluous. You can add even more braces like:
AnonymousClass(x);
AnonymousClass((x));
AnonymousClass(((x)));
AnonymousClass((((x))));
//and so on
All of them are same as:
AnonymousClass x;
Demo: http://www.ideone.com/QnRKH
You can use the syntax A(x) to create anonymous object, especially when calling a function:
int x = 10;
f(A(x)); //1 - () is needed
f(A((((x))))); //2 - extra () are superfluous
Both line 1 and 2 call a function f passing an object of type A :
http://www.ideone.com/ofbpR
But again, the extra parentheses are still superfluous at line 2.
You're missing an actual name for your variable/object:
AnonymousClass myclass(x);
Instead of that you could as well write...
AnonymousClass (myclass)(x);
So your line of code results in this:
AnonymousClass (x);
Or more common:
AnonymousClass x;
Why it happens? Brackets are just there for logical grouping ("what belongs together?"). The only difference is, they're forced for arguments (i.e. you can't just write AnonymousClass myclass x).
To avoid such a mistake, just remember one rule: If you declare an anonymous object with one argument, just place it into a pair of parentheses!

Explain GCC error after using an object accidentally declared as a function

The following is a common typo with language newcomers, who think that they are defining an object but are actually declaring a function:
struct T
{
void foo() {}
};
int main()
{
T obj();
obj.foo();
}
GCC 4.1.2's error is:
In function 'int main()':
Line 9: error: request for member 'foo' in 'obj', which is of non-class type 'T ()()'
compilation terminated due to -Wfatal-errors.
Why is the reported type in the message T ()()? I'd have expected T ().
IIRC this is just a compiler bug. GCC 4.4 says T() while 4.2 says T()() for me.
The error is best understood when you realize that you usually don't write out function types without naming at least the function, but it's a bit more common for function pointers.
For instance, int (*fooPtr)() names the pointer. If you omit the name, you have int (*)(). Now, going from function pointer to function type would give you int ()().
There's no real standard here, because ISO C++ doesn't define canonical names for all types. For instance, const volatile int is the same type as volatile const int, and neither form is canonical.

Error while writing static function?

Error while writing static function.
static int function_name ( const Reference< data_type>* ptr)
{
}
when i wrote a static functin which takes Reference pointer then ir gives me following error
error: ISO C++ forbids declaration of 'Reference' with no type
error: expected ',' or '...' before '<' token
The compiler is complaining because it doesn't know what a Reference<T> is. Either you've forgotten to #include the header file that it is defined in, or you've forgotten to forward-declare it.
You presumably mean Reference to be a template but the compiler doesn't see it as one.