function returning a struct in c++? - 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.

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.

GCC attribute warning with trailing return type when return type is a class

GCC 4.9.1 does not appear to like function declarations with a trailing return type with attributes when the return type is a class.
Consider this following simplistic testcase:
struct bar
{
int a;
bar (int a) : a(a) {}
};
auto foo() -> bar __attribute__((unused));
auto foo() -> bar { return bar(5); }
int main()
{
return 0;
}
GCC prints a bizarre warning in regards to the attribute:
argh.cpp:2:41: warning: ignoring attributes applied to class type ‘bar’ outside of definition [-Wattributes]
auto foo() -> bar __attribute__((unused)) {return bar(5);}
Merging the declaration with the definition does not silence the warning, and this only happens when the return type is a class-type, it works fine with int. What is going on? Why does GCC not like this particular function declaration?
Seems to be a bug in the attribute parser used by GCC. The GCC manual warns about potential problems with the attribute grammar :
6.31 Attribute Syntax
Because of infelicities in the grammar for attributes, some forms
described here may not be successfully parsed in all cases.
There are some problems with the semantics of attributes in C++. [...] For example, there are no manglings for attributes, although they may affect code generation, so problems may arise when attributed types are used in conjunction with templates or overloading.
A warning about attribute parsing after a trailing return type would be helpful too.
An attribute specifier list may appear immediately before a declarator
[...]
You should try to place the attribute before the prototype :
__attribute__((unused))
auto foo() -> bar ;
auto foo() -> bar { return bar(5); }
and it should be OK without any warning.
An attribute specifier list may appear immediately before the comma, =
or semicolon terminating the declaration of an identifier other than a
function definition. Such attribute specifiers apply to the declared
object or function.
I guess that positioning the function attribute after the function declaration is OK unless there is a trailing return type.
Clang (as usual) gives a better warning in this case:
example.cpp:7:34: warning: 'unused' attribute ignored when parsing type
[-Wignored-attributes]
auto foo() -> bar __attribute__((unused));
^~~~~~
1 warning generated.
Just like GCC is telling you, that attribute is meaningless in the context you're using it. It's conceptually the same as doing something like:
const int f(void) { return 5 };
The const there just doesn't mean anything.
The GCC manual implies that the syntax is not supported at the moment.
An attribute specifier list may, in future, be permitted to appear
after the declarator in a function definition (before any old-style
parameter declarations or the function body).
N3337 describes the grammar of a function definition in [dcl.fct.def]:
function-definition:
attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt function-body
...
2 The declarator in a function-definition shall have the form
D1 ( parameter-declaration-clause )
cv-qualifier-seqopt
ref-qualifieropt
exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt
As you can see the trailing-return-type is part of the declarator which appears before the function-body. Try changing your code to this:
auto __attribute__((unused)) foo() -> bar;

How to call this function template?

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.

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!

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.