Strange Syntax in C++ - c++

Recently I've been facing a really strange way to write a protoype :
void myProto( QList<::myObject::myStruct> myStructList );
And I'd like to know what does "<::" and ">" mean ?
Thanks !

QList is a template, and QList<Type> is a specialization of that template, with the actual type ::myObject::myStruct.
The :: is the scope resolution operator, which tells the compiler to look for myStruct in the scope of myObject, which itself is at global scope.

::myObject::myStruct
means refer to myStruct defined in class (or namespace) myObject which is located at global scope.
<>
A type goes inside these brackets and it indicates the specialization of the template for that type.

Compile the following program
struct A // GLOBAL A
{
void f()
{ }
};
namespace nm
{
struct A // nm::A
{ };
template <class T>
struct B
{
T a;
};
void f1(B<A> b) // WILL NOT COMPILE
{
b.a.f();
}
void f2(B< ::A> b) // WILL COMPILE
{
b.a.f();
}
}
int main()
{
}
nm::f1 will not compile
nm::f2 will compile
This is because ::A (the global A) has a f member
and
nm::A doesn't have a f member.

Related

Returning anonymous struct

It seems you can return an unnamed struct this way:
auto foo() {
struct {
int bar;
int square() {
return bar * bar;
}
} a { 7 };
return a;
}
Is there anyway to do this without the redundant variable name a, thus anonymously?
For starters C++ does not define anonymous structures. I think you mean an unnamed structure.
According ro the C++ Standard the return statement is defined like (8.6 Jump statements)
return expr-or-braced-init-listopt ;
So you may not use a declaration in the return statement. If so then you need prelimary to declare an object of the structure type that will be returned.
I have no idea what the point of this exercise is, so here is an answer that technically does what you ask for:
auto helper()
{
struct {
int x;
} a {0};
return a;
}
decltype(helper()) foo()
{
return {8};
}
https://godbolt.org/z/zA8C1V
The struct is unnamed.
foo does not return a named variable.
Of course this is straight up ridiculous - one would just name the struct instead of this decltype tomfoolery.
No, this is not possible.
The closest you can get is to use a functional-style cast to create a temporary, and use a C99-style scoped-initialiser; GCC allows this in C++ mode, as an extension:
#include <iostream>
#include <string>
auto foo() {
return (struct {
int bar;
int square() {
return bar * bar;
}
}) { 7 };
}
… but this is not portable (and will warn).
Without the braces around 7 the extension is not triggered, and you're back to standard code, in which it is illegal to define a type in a cast.
Instead of writing obtuse code, give your type a name and give your object a name. Your readers will thank you.
None of
struct {/*...*/} foo() { // Illegal
return {/*...*/};
}
auto foo() {
return struct { /*...*/ } { /*...*/ }; // Illegal
}
template <typename T = struct { /*...*/ }> // Illegal
T foo() {
return { /*...*/ };
}
are legal.
You have to, at least, have a named type, or a named instance.
Lambda allows to have neither, but you can only capture and define its operator():
auto foo() {
return [/*...*/](/*...*/) { /*...*/ }; // Legal
}
Returning anonymous struct
There is no such thing as anonymous struct in C++. That's enough to make it impossible.
There is a - limited - way of returning an object of anonymous type from a function: Returning a lambda.
auto make_square_function() {
return [bar = 7]() {
return bar * bar;
};
}
Lambdas are much more limited than general classes though. The members (captures) are encapsulated and cannot be named from the outside of the lambda and there are no member functions other than the function call overload.
Is there anyway to do this without the redundant variable name a
Only if you give the class a name:
struct Squarer {
int bar;
int square() {
return bar * bar;
}
};
auto foo() {
return Squarer{7};
}
Returning an instance of unnamed class is only possible by defining a variable.
Just for fun, another define-the-variable-in-another-function solution (taking inspiration from Max Langhof's answer)
auto foo ()
{
return []{ struct{int bar;} a {7}; return a; }();
}
No, because you need to return an instance of an object, in this case a.
The returned object has to exist somewhere in memory, you can't just return a class definition.
In your example, you don't return an anonymous struct, but you return an instance of that struct.

Why can I access a struct defined inside a function from outside the function through return type deduction?

I was watching one of Jason Turner's videos and I saw that you can define a type inside a function scope and have it available outside of that scope through function return type deduction.
auto f()
{
struct MyStruct
{
int n;
};
return MyStruct{};
}
int main()
{
auto a = f().n;
return a;
}
Why is this allowed? Is there a paragraph in the C++ 14 standard that allows this?
When trying to get the typeid of MyStruct with clang in compile explorer I saw in the assembly output the type displayed as f()::MyStruct, so there is a scope, but somehow I can access MyStruct outside of that scope. Is this some kind of ADL thing?
No, there's no ADL involved. Since your translation unit contains the definition of the structure, there's no problem in accessing its members.
The important point is that types don't really exist in scopes: names do. And notice that there's no way for you to use the identifier MyStruct instead of auto when declaring a. The name is as inaccessible as it should be. However, as long as you can get at the type without using the inaccessible name, all is fine.
In principle, this is hardly different from using a private member type:
class X
{
struct Hidden
{
int i;
};
public:
Hidden get() const { return {42}; }
};
int main()
{
X x;
auto h = x.get();
assert(h.i == 42);
}

Template inheritance: There are no arguments that depend on a template parameter [duplicate]

This question already has an answer here:
g++ template parameter error
(1 answer)
Closed 6 years ago.
I came across this error when compiling the following code.
After doing some research and reading similar errors in different situations, I came up with the solution I needed.
But I did not fully understood the undelying reason for the error and the fix.
template <typename T>
class TestA {
int a;
T temp;
protected:
int b;
public:
int c;
TestA(T te): a{10}, b{20}, c{30}, temp{te} {}
int geta(){ return a; }
int getb(){ return b; }
int getc(){ return c; }
};
template <typename T>
class TestB {
int atb;
T tempb;
protected:
int btb;
public:
int ctb;
TestB(T te) atb{10}, btb{20}, ctb{30}, tempb{te} {}
};
template <typename T>
class TestInh : public TestA<T>, public TestB<T> {
int aa;
T temptemp;
protected:
int bb;
int b;
public:
int cc;
TestInh(T te) : TestA<T>{te}, TestB<T>{te}, bb{10000}, b{-1000} {}
int get_total() {
// The error happens here!
return geta();
}
};
int main(int argc, char const *argv[]) {
char text = 'a';
TestInh<char> test(text);
//std::cout << test.geta() << std::endl;
std::cout << test.get_total() << std::endl;
//std::cout << test.c << std::endl;
return 0;
}
When compiling this code, I got this error:
testtemplate.cc: In member function ‘int TestInh<T>::get_total()’:
testtemplate.cc:54:32: error: there are no arguments to ‘geta’ that depend on a template parameter, so a declaration of ‘geta’ must be available [-fpermissive]
int get_total() {return geta();}
^
testtemplate.cc:54:32: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
It is solved by calling this->geta() instead of just geta(), but I do not fully understand why this cannot be resolved by the compiler.
Can someone please explain me why?
When extending a class that depends on a template parameter, this kind of become a dependent name.
The problem is that while performing two phase name lookup, the compiler can't know where he can find the function geta. He cannot know it comes from the parent. Because template specialization is a thing, TestA<int> and TestA<double> could be two completely different clas swith different functions and members.
With the this keyword added, the compiler know that geta must be a member function.
Without that, it could be either a member function or non-member function, or a member function of TestB.
Imagine a template code that will either call a function geta from TestA and geta from TestB depending on some template conditions. Ouch. The compiler want to be sure that the code is consistent for every template instantiations.
Another way of saying to the compiler that the function exist as a member function is to add a using statement:
template <typename T>
struct TestInh : TestA<T>, TestB<T> {
// some code...
using TestA<T>::geta;
int get_total() {
// works! With the above using statement,
// the compiler knows that 'geta()' is
// a member function of TestA<T>!
return geta();
}
};

Name spaces in c++ and c

Not that I would ever write the code like the following in my professional work, the following code is legal and compiles without warnings in c++ and c:
#include <stdlib.h>
typedef struct foo { int foo; } foo;
foo * alloc_foo () {
return (struct foo*) malloc(sizeof(foo));
}
struct foo * alloc_struct_foo () {
return (foo*) malloc(sizeof(struct foo));
}
foo * make_foo1 (int val) {
foo * foo = alloc_struct_foo ();
foo->foo = 0;
return foo;
}
struct foo * make_foo2 (int val) {
struct foo * foo = alloc_foo();
foo->foo = 0;
return foo;
}
What makes this legal and unambiguous in C is section 6.2.3 of the C standard:
6.2.3 Name spaces of identifiers
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers (label names; tags of structures, unions, and enumerations; members of structures or unions; and ordinary identifiers).
Note that thanks to label names living in their own name spaces, I could have made the code even more obfuscated by using a label foo somewhere.
Add the following and the code does not compile:
int foo (foo * ptr) {
return ++ptr->foo;
}
So, two questions, one related to C and C++ and the other, C++.
C/C++ question: Why can't I define the function foo?
It seems I should be able to define the function foo; function names and variable names are "ordinary identifiers". But if I add that last little bit of code I get error: redefinition of 'foo' as different kind of symbol.
Question: foo * foo; is perfectly legal, so why isn't int foo (foo*); legal?
C++ question: How does this work at all in C++?
The meaning of "name space" takes on a rather different meaning on in C++ than in C. I can't find anything in the C++ standard that talks about the C concept of name spaces, which is what makes the above legal in C.
Question: What makes this legal in C++ (chapter and verse preferred)?
foo * foo; is perfectly legal, so why isn't int foo (foo*); legal?
Because there already is a type named foo in the same declaration context as your function. You cannot have a type and a function of the same name in the same scope.
How does this work at all in C++?
Because you are allowed to hide names in nested scopes. When you declare foo * foo, the first foo refers to the type. The second foo declares a variable -- at that point, the type foo is hidden. Try declaring foo * baz after foo * foo, it should fail.
struct foo {};
void test() {
foo * foo; // first `foo` is the type, second `foo` is the variable
foo * baz; // first `foo` is the variable
}
In C++11 3.3.1/4 says that in a declarative region all declarations of a name must refer to the same entity (or an overload set). There's an exception that allows you to use a class name for a set of function names (so foo() hides class foo) but this doesn't apply if you have a typedef (which you do).
Try it with the typedef struct foo foo omitted in C++.
This doesn't work in C++ either ... the problem is that the pre-processor for gcc/g++ is looking for __cplusplus, not cplusplus. Therefore you pre-processor statements
#if defined FOO && ! defined cplusplus
#undef FOO
#endif
do not work correctly.
Because there is already function foo() it's a default constructof for struct foo
typedef struct foo
{
int a;
foo(int val)
:a(val)
{}
} foo;
int foo(int value)
{
cout << value <<endl;
}
void main()
{
foo foovar = foo(50); // constructor foo or function foo?
}
There are no such things as constructors in C.
Edit specially for Alan Stokes:
typedef struct foo
{
int a;
foo(int val, double val2)
:a(val)
{
cout << val2 << endl;
}
} foo;
int foo(int value, double val2)
{
cout << value << val2 << endl;
}
void main()
{
some_random_func(foo(50, 1.0)); // constructor foo or function foo?
}

How do I call a friend template function defined inside a class?

I got this example from my book, but I have no idea how to actually call the ticket function. This is the code:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
I get the "candidate function(s) not accessible" error message.
A few points will help you figure out what's going on here:
I) Friend function definitions within classes can only be found by Argument dependent lookup when called from outside the class definition.
II) Function templates that are supplied explicit template arguments do not undergo ADL unless the compiler is given some explicit help in identifying the call as a function call.
III) Argument dependent lookup (ADL) only works for user defined types.
A few examples will better illustrate each of the above points:
//------------------------
struct S
{
friend int f(int) { return 0; } // 1
friend int f(S) { return 0; } // 2
};
S s;
int i = f(3); // error - ADL does not work for ints, (III)
int j = f(s); // ok - ADL works for UDTs and helps find friend function - calls 2 (III)
// so how do we call function 1? If the compiler won't find the name via ADL
// declare the function in the namespace scope (since that is where the friend function
// gets injected)
int f(int); // This function declaration refers to the same function as #1
int k = f(3); // ok - but not because of ADL
// ok now lets add some friend templates and make this interesting
struct S
{
friend int f(int) { return 0; } // 1
friend int f(S) { return 0; } // 2
template<class T> friend int g(int) { return 0; } // 3
template<class T> friend int g(S) { return 0; } // 4
template<class T> friend int g() { return 0; } // 5
};
S s;
int k = g(5); // error - no ADL (III)
int l = g(s); // ok - ADL - calls 4
int m = g<int>(s); // should call 4 - but no ADL (point II above)
// ok so point II above says we have to give the compiler some help here
// We have to tell the compiler that g<int> identifies a function
// The way to do that is to add a visible dummy template function declaration
template<class /*Dummy*/, class /*TriggerADL*/> void g();
int m = g<int>(s); // ok - compiler recognizes fun call, ADL triggered - calls 4
int n = g<int>(3); // still not ok - no ADL for ints
// so how do we call either function 3 or 5 since we cannot rely on ADL?
// Remember friend functions are injected into the outer namespace
// so lets just declare the functions in the outer namespace (as we did above)
// both these declarations of g below refer to their counterparts defined in S
template<class T> int g(int);
template<class T> int g();
int o = g<int>(3); // ok
int p = g<int>(); // ok
// Of course once you have these two declarations at namespace scope
// you can get rid of the Dummy, TriggerADL declaration.
Ok so now lets return to the Vandevoorde example that you quoted, and now this should be easy:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int Manager::counter;
template<class T> int ticket(); // <-- this should work with a conformant compiler
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
Hope that helps :)
Hotfix
There is a hot-fix available, but read the below explanation if you want to understand what's going on.
#include <iostream>
template<typename T> int ticket();
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int Manager::counter; // don't forget the definition
int main() {
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
As the snippet shows, you have to declare the template to make it visible when you call it.
Friend function definitions
This is confusing, since there are some rules in the way in this case. Some basic points, and then some other points.
struct A {
friend void f(A*) { std::cout << "hello"; }
};
What does it do? It defines a friend function. Such a function is a member of the enclosing namespace. It's not a class member, even though it is defined within a class! The fact that it's defined within a class only changes the lexical scope of that function: It can refer to that class' members directly, without preceding the class-name.
Most importantly, though, the function is not visible after being declared. You cannot take its address doing something like this, for example
&f
The only way that the function would work is using argument dependent lookup. A lookup that ends up having that class as its associated class will consider that friend function. That means that the following works:
f((A*)0);
It works because the call includes an argument with type that has the class included. In that case, the class is an associated class, and the friend declaration will be considered.
The following won't work, for example
f(0);
Because it has no idea that it should look within A to find a friend declaration. A friend function definition of a function without an argument won't be found, because there is no argument dependent lookup happening, then.
Friend function definition for templates
In addition to the fact that your call does not include arguments, it has another problem. If you define a friend function template, the matter is more complicated. There is a rule that says that if the compiler sees T<A1, A2, A3>, that this only refers to a template specialization if T actually resolves to a template. Consider
ticket < int > ()
The compiler can't resolve ticket, because it is not visible to normal lookup. Therefor, the rule says that ticket<int> does not refer to a function. It has to be parsed as a relational expression, yielding to the following
(ticket < int) > ()
That will be a syntax error, because int is not a value, and () is neither a value.
Example
Here is an example where it matters.
struct A {
template<int I> friend void f(A*) { }
};
// try to comment this out
template<typename Dummy> void f();
int main() {
f<1>((A*)0);
}
That compiles. It compiles because f resolves to a template (although a completely different one that can't even accept a non-type template argument - but that doesn't matter!). But a Standard conforming compiler will not compile the snippet once you comment out the second declaration, because it's compiled as a relational expression (less-than and smaller-than) and it will not find symbol f.
Read this thread for further information: What am I missing in this template toy example?.
I do get the same error using the MS VS++ compiler. According to the docs on MSDN:
http://msdn.microsoft.com/en-us/library/h2x4fzdz(VS.80).aspx
Friends are not in the class's scope,
and they are not called using the
member-selection operators (. and –>)
unless they are members of another
class. A friend function is declared
by the class that is granting access.
So friend functions are not actually part of the class and should therefore not be defined in class scope. Define the function outside of the class:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket();
static int counter;
};
template<typename T>
int ticket() {
return ++Manager::counter;
}
int Manager::counter;
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
Why not make it static instead?
#include <iostream>
class Manager {
public:
template<typename T>
static int ticket()
{
return ++Manager::counter;
}
static int counter;
};
int main()
{
Manager m;
std::cout << "ticket: " << Manager::ticket<int>() << std::endl;
}
Though really, it doesn't have to be a template either. I assume you needed information specifically about friend templates?