I would like to know, when someone gives you a template for a default constructor in C++ and in the parameter there is a series of unnamed variables that somehow are assigned values. What does this mean?
Is this legal?
How can one access these variables?
Example I received:
IntSet::IntSet(int = -1, int = -1, int = -1, int = -1); //default constructor
I would appreciate any answers that clarify this use!
It's perfectly legal to not name the arguments in the declaration or in the definition of a function. It's also perfectly legal to use different names for a given argument in the declaration and definition.
Note that if a parameter that is not named in the definition is not accessible. Why do this? A lot of compilers can be made to complain about unused arguments. Most compilers won't complain if the function definition doesn't name those unused arguments.
About unnamed parameters in a declaration, which is the topic of this question: Just because doing this is legal doesn't necessarily mean it's a good practice. Those unnamed arguments in a function declaration might be fine for a compiler, but they aren't fine for a human reader. No name = zero communication. The documentation and header file should contain everything that an external user needs to know regarding how to use the class. RTFM and maybe RTFH (read the fine manual / read the fine headers). That "F" word ("fine") in RTFM and RTFH takes on a different meaning in RTFC.
Those unnamed arguments in a header are almost inevitably coupled with poor documentation. As an external user, this forces me to read the function's definition to understand how to use a function. RTFC. It is not fine when an external user has to read the implementation to determine what is going on.
That means that if you call it without passing parameters, the parameters will take the values you passed.
So if you call
IntSet* i = new Intset();
would be equivalent to calling
Intset* i = new IntSet(-1,-1,-1,-1)
About the unnamed part. I would assume because it is part of a library that uses templates. The nameless parameters are not used, but are there so it matches the signature of another class that may need them. In the case that it needs them, it will just pass -1 by default.
You can take a look at this link for an example:
http://compgroups.net/comp.lang.c++/unnamed-formal-parameter/1004784
I am copying the example from the above reference here, to make the case for using such a construct in an useful way
For instance
class A
{
public:
A(void* = 0) {} // unused parameter
};
class B
{
public:
B(void* p) : pp(p) {} // used parameter
private:
void* pp;
};
template <class T>
class C
{
public:
static T* create(void* p = 0) { return new T(p); }
};
int main()
{
A* a = C<A>::create();
B* b = C<B>::create("hello");
}
C::create would not compile unless A::A had a parameter even though it is
not used.
Related
How do lines (2) and (3) even compile in the following C++ class, given that this is a pointer, so should need -> notation to access fields (as seen in line (1))? (Source)
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
template <typename T>
class sptr_wrapper
{
private:
boost::shared_ptr<T> sptr;
public:
template <typename ...ARGS>
explicit sptr_wrapper(ARGS... a)
{
this->sptr = boost::make_shared<T>(a...);
}
explicit sptr_wrapper(boost::shared_ptr<T> sptr)
{
this->sptr = sptr; // (1)
}
virtual ~sptr_wrapper() noexcept = default;
void set_from_sptr(boost::shared_ptr<T> sptr)
{
this.sptr = sptr; // (2)
}
boost::shared_ptr<T> get_sptr() const
{
return sptr; // (3)
}
};
The line (2) is invalid. As you said, this is a pointer, we need to use -> instead of .
As the member of class template, sptr_wrapper::set_from_sptr is not required to be instantiated, until it's used. So you can add some code trying to call it, then you might get compile-errors as you expect.
This applies to the members of the class template: unless the member is used in the program, it is not instantiated, and does not require a definition.
The line (3) is valid; sptr refers to the member sptr, which has the same effect as this->sptr.
When a non-static class member is used in any of the contexts where the this keyword is allowed (non-static member function bodies, member initializer lists, default member initializers), the implicit this-> is automatically added before the name, resulting in a member access expression (which, if the member is a virtual member function, results in a virtual function call).
Would you believe that the reason this compiles is because nothing really gets compiled here?
The shown code defines a template.
A template does not become "real" until it instantiates a class. Only at that time the compiler gets a closer look at the template, and attempts to figure WTF it's doing.
Sure, when defining a template the compiler makes a half-hearted attempt to parse the template, but only barely enough to satisfy itself that the template consists of some plausibly-looking C++ code.
If you add some additional lines to the shown code you'll get the compilation errors you were yearning for:
class X {};
void foo()
{
sptr_wrapper<X> x;
boost::shared_ptr<X> y;
x.set_from_sptr(y);
}
And this produces the compilation errors you were looking for:
t.C:27:14: error: request for member ‘sptr’ in ‘(sptr_wrapper<X>*)this’, which is of pointer type ‘sptr_wrapper<X>*’ (maybe you meant to use ‘->’ ?)
27 | this.sptr = sptr; // (2)
Note that merely instantiating
sptr_wrapper<X> x;
isn't enough. You have to go full throttle and invoke the method in question, before it becomes "real" in the eyes of a C++ compiler, and it chokes on it.
It's true that I can quite think of any circumstance where "this.foo" might be valid C++ code, but I'm sure that somewhere in the 2000 pages that make up the current C++ standard, the exact details of what's going on gets spelled out in a very pedantic way.
And you might consider dropping a note to your compiler's bug tracker, a feature request to have your compiler issue a friendly warning, in advance, when it sees something like this.
I am trying to understand the following code that I saw today. I already tried to find a related question, but since I have no idea what this feature of C++ is called it is hard to find related posts. A hint on the correct search term might already help me.
struct A
{ int x; };
struct B
{ B(A a) {}; };
int main()
{
B b{ { 5 } }; // works, seems to create a struct A from {5} and pass it to B's constructor
std::make_unique<B>({ 5 }); // doesn't compile
return 0;
}
Why is {5} not used to create a struct A when passed to make_unique but is used this way in the constructor of B?
If B had a second constructor B(int foo) {}; this one would be used instead of the one frome above (at least that is what I found by trial and error). What is the rule to decide if the argument is automatically used to create a struct A or if it is used directly as int in the constructor?
I am using Visual C++ 14.0
Here's a simplified demonstration:
struct X { X(int); };
void foo(X );
template <typename T> void bar(T );
foo({0}); // ok
bar({0}); // error
The issue is that braced-init-lists, those constructs that are just floating {...}s, are strange beasts in C++. They don't have a type - what they mean must be inferred from how they're actually used. When we call foo({0}), the braced-init-list is used to construct an X because that's the argument - it behaves as if we wrote X{0}.
But in bar({0}), we don't have sufficient context to know what to do with that. We need to deduce T from the argument, but the argument doesn't have a type - so what type could we possibly deduce?
The way to make it work, in this context, is to explicitly provide that T:
bar<X>({0}); // ok
or provide an argument that has a type that can be deduced:
bar(X{0}); // ok
In your original example, you can provide the A directly:
make_unique<B>(A{5})
or the B directly:
make_unique<B>(B({5}))
or just use new:
unique_ptr<B>(new B({5}))
or, less preferred and somewhat questionable, explicitly specify the template parameter:
make_unique<B, A>({5});
A constructor with a single non-default parameter (until C++11) that is declared without the function specifier explicit is called a converting constructor. Your A and B are instances of such constructors (this explains, why your first call works fine.) The problem is, that std::make_unique impedes these explicit calls. Anyhow, it might be a good idea, to not trust in these automatic creation in the first place and spent a few chars to show types. This could improve the readability of the code.
suppose we have a class
class Foo {
private:
int PARTS;
public:
Foo( Graph & );
int howBig();
}
int Foo::howBig() { return this->PARTS; }
int Foo::howBig() { return PARTS; }
Foo::Foo( Graph &G ) {
<Do something with G.*>
}
Which one of howBig()-variants is correct?
The &-sign ensures that only the reference for Graph object
is passed to initialization function?
In C I would simply do something like some_function( Graph *G ),
but in C++ we have both & and *-type variables, never understood
the difference...
Thank you.
When you've local variable inside a member function, then you must have to use this as:
Foo::MemberFunction(int a)
{
int b = a; //b is initialized with the parameter (which is a local variable)
int c = this->a; //c is initialized with member data a
this->a = a; //update the member data with the parameter
}
But when you don't have such cases, then this is implicit; you need to explicity write it, which means in your code, both versions of howBig is correct.
However, in member initialization list, the rules are different. For example:
struct A
{
int a;
A(int a) : a(a) {}
};
In this code, a(a) means, the member data a is being initialized with the parameter a. You don't have to write this->a(a). Just a(a) is enough. Understand this visually:
A(int a) : a ( a ) {}
// ^ ^
// | this is the parameter
// this is the member data
You can use this-> to resolve the dependent name issue without explicitly having to spell out the name of the base. If the name of the base is big this could arguably improve readability.
This issue only occurs when writing templates and using this-> is only appropriate if they're member functions, e.g.:
template <typename T>
struct bar {
void func();
};
template <typename T>
struct foo : public bar {
void derived()
{
func(); // error
this->func(); // fine
bar<T>::func(); // also fine, but potentially a lot more verbose
}
};
Which one of howBig()-variants is correct?
both in your case, the compiler will produce the same code
The &-sign ensures that only the reference for Graph object is passed to initialization function? In C I would simply do something like some_function( Graph *G ), but in C++ we have both & and *-type variables, never understood the difference...
there is no difference as per the use of the variable inside the method(except syntax) - in the case of reference(&) imagine as if you've been passed an invisible pointer that you can use without dereferencing
it(the &) might be "easier" for clients to use
Both forms of Foo::howBig() are correct. I tend to use the second in general, but there are situations that involve templates where the first is required.
The main difference between references and pointers is the lack of "null references". You can use reference arguments when you don't want to copy the whole object but you want to force the caller to pass one.
Both are correct. Usually shorter code is easier to read, so only use this-> if you need it to disambiguate (see the other answers) or if you would otherwise have trouble understanding where the symbol comes from.
References can't be rebound and can't be (easily) bound to NULL, so:
Prefer references to pointers where you can use them. Since they cannot be null and they cannot be deleted, you have fewer things to worry about when using code that uses references.
Use const references instead of values to pass objects that are large (more than say 16 or 20 bytes) or have complex copy constructors to save copy overhead while treating it as if it was pass by value.
Try to avoid return arguments altogether, whether by pointer or reference. Return complex object or std::pair or boost::tuple or std::tuple (C++11 or TR1 only) instead. It's more readable.
Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.
Hello,
It wasn't for just a few times that I stumbled into an object construction statement that I didn't understand, and it was only today that I noticed what ambiguity was being introduced by it. I'll explain how to reproduce it and would like to know if there's a way to fix it (C++0x allowed). Here it goes.
Suppose there is a class whose constructor takes only one argument, and this one argument's type is another class with a default constructor. E.g.:
struct ArgType {};
class Class
{
public:
Class(ArgType arg);
};
If I try to construct an object of type Class on the stack, I get an ambiguity:
Class c(ArgType()); // is this an object construction or a forward declaration
// of a function "c" returning `Class` and taking a pointer
// to a function returning `ArgType` and taking no arguments
// as argument? (oh yeh, loli haets awkward syntax in teh
// saucecode)
I say it's an object construction, but the compiler insists it's a forward declaration inside the function body. For you who still doesn't get it, here is a fully working example:
#include <iostream>
struct ArgType {};
struct Class {};
ArgType func()
{
std::cout << "func()\n";
return ArgType();
}
int main()
{
Class c(ArgType());
c(func); // prints "func()\n"
}
Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works
{
funcPtr();
return Class();
}
So well, enough examples. Anyone can help me get around this without making anything too anti-idiomatic (I'm a library developer, and people like idiomatic libraries)?
-- edit
Never mind. This is a dupe of Most vexing parse: why doesn't A a(()); work?.
Thanks, sbi.
This is known as "C++'s most vexing parse". See here and here.
Let's simplify a little.
int f1();
What's that? The compiler (and I) say it's a forward declaration for a function returning an integer.
How about this?
int f2(double );
The compiler (and I) say it's a forward declaration for a function taking a double argument and returning an int.
So have you tried this:
ClassType c = ClassType(ArgType());
Check out the c++ faq lite on constructors for explanations and examples
Based on the "C++0x allowed", the right answer is (probably) to change the definition to:
Class c(ArgType {});
Simple, straightforward and puts the burden entirely on the user of the library, not the author!
Edit: Yes, the ctor is invoked -- C++ 0x adds List-Initialization as an unambiguous way to delimit initializer lists. It can't be mis-parsed like in your sample, but otherwise the meaning is roughly the same as if you used parentheses. See N3000, the third bullet point under §8.5.4/3. You can write a ctor to receive an initializer list as a single argument, or the items in the initializer list can be matched up with the ctor arguments individually.
the question is simple...
is there any difference in using this->yourvariable or yourvariable directly for some reason?
I am not finding any problem with that, but I am using this-> a lot and would like to know if there is any difference before going further.
I saw a comment on a post here and I don't remember which thread, but the person said something about using the keyword "this".
Personally, I find it nice to use than the variable directly. It makes the code more easier and pretty.
Joe
In most cases there is no difference. But there are situations where it makes a difference:
class foo
{
int i;
void bar() {
int i = 3;
i; // refers to local i
this->i; // refers to the member i
}
};
Also, with templates you may need to qualify a member with this-> so that name lookup is delayed:
template<typename T>
struct A
{
int i;
T* p;
};
template<typename T>
struct B : A<T>
{
void foo() {
int k = this->i; // here this-> is required
}
};
A compiler that properly does the "two phase lookup" will complain in case you remove "this->" that it doesn't know what i is supposed to be. "this->" tells it that it's a member from a base class. Since the base class depends on a template parameter, lookup is delayed until the class template is instantiated.
No, there is no real difference, it is simply a scope qualifier. However, suppose a method
void SetFoo( Foo foo )
{
this->foo = foo;
}
where this->foo is a private member. Here it allows you to take a parameter with the same name as a class/instance variable.
I find that using this makes my code more readable, but there's no reason that you have to. If you look at the assembler code your compiler generates, it should be functionally (and usually literally) identical.
Basically, when the function is called, it is passed a hidden argument this which is then used to figure out which variables are where. If you use the variables directly, without a this->, you're not doing anything except making use of some syntactic sugar.
This was kind of asked and answered about C# here and I think that the answer (at least mine) is the same. It is preference.