what's the situation that you must use "this" pointer? [duplicate] - c++

This question already has answers here:
Is there any reason to use this->
(16 answers)
Closed 7 years ago.
I have a code working like:
class base {
....
protected:
typeA m_mem;
}
class mymodule: public base{
....
void function(){
m_mem.call();
}
}
This was working OK before. Suddenly, I see it brokes saying "m_mem was not declared...." It might be some other people changed the namespace or other parts.
And I found it was working by just adding "this" then it compiles fine
this->m_mem.call()
While I just would like to know what's the cases that I must use "this" ? I learned "this" can be used to point to distinguish between class member and argument names. While for my case, what can be the reason that I must use "this" for accessing a data member

This can occur for example when you use templates.
The compiler will issue an error that x is an undefined variable for these class definitions
template <class T>
struct A
{
int x;
};
template <class T>
struct B : A<T>
{
void set_x( int v ) { x = v; }
};
If you write
void set_x( int v ) { this->x = v; }
the code will compile.

Related

Why in a C++ template, declaring a vector<T> member variable as static will produce linker error but inline static will not? [duplicate]

This question already has answers here:
How to initialize private static members in C++?
(18 answers)
Closed 2 years ago.
I cannot explain the following (using C++20 rules)
//FooTemplate.h
template<typename T>
class FooTemplate {
private:
static std::vector<T> t; //linker error.
//inline static std::vector<T> t; --> will not produce linker error
//static T t; -->this works also with the appropriate changes in the following code
public:
static void setT(T t1)
{
t.push_back(t1);
}
static T getT(int i)
{
return t.at(i);
}
};
//main.cpp
#include"FooTemplate.h"
int main() {
FooTemplate<Foo>::setT(Foo{});
FooTemplate<Foo>::getT(0);
}
I have to inline the static member t in order for it to work. If I do not use a templated container (e..g define T t instead of vector<T> t it also works.
Any idea?
Static members must be defined (initialized) outside their class.
Simply write in your implementation:
template<class T> std::vector<T> FooTemplate<T>::t = [some initializer];
EDIT: You do not actually need to explicitely initialize them (unless they are objects of a class without a default constructor), but you do need to repeat their declaration like this anyway.

a call to a method from base template fails to compile [duplicate]

This question already has an answer here:
Why can I call base template class method from derived class
(1 answer)
Closed 2 years ago.
I have a template struct which inherits another template struct. It fails compilation in different compilers (in VS2017 and clang on linux). A simple change in the code fixes it.
The code is:
template<typename T>
struct base {
int GetValue2() { return 0; }
};
template<typename T>
struct derived : public base<T>
{
int GetValue() { return GetValue2(); }
};
int main() {
derived<int> a;
return 1;
}
If I change the line
int GetValue() { return GetValue2(); }
to:
int GetValue() { return this->GetValue2(); }
everything compiles just fine.
Does anyone have an idea what's going on?
There is a two-stage name lookup here.
In GetValue(), GetValue2 is not used in a dependent context, so the compiler will look for a name declared at the enclosing namespace scope (which is the global scope here).
It will not look into the base class, since that is dependent and you may declare specializations of Base even after declaring Derived, so the compiler can't really know what i would refer to. If there is no global variable i, then you will get an error message.
In order to make it clear that you want the member of the base class, you need to defer lookup until instantiation time, at which the base class is known. For this, you need to access i in a dependent context, by either using this->i (remember that this is of type Derived*, so is obviously dependent), or using Base::i. Alternatively, Base::i might be brought into scope by a using-declaration.
template<typename T>
struct base {
int GetValue2() { return 0; }
};
template<typename T>
struct derived : public base<T>
{
int GetValue_using() {
using base<T>::GetValue2; // won't compile with gcc, place it outside the function (ok with clang and msvc)
return GetValue2();
}
int GetValue_this() { return this->GetValue2(); }
int GetValue_base() { return base<T>::GetValue2(); }
};
int main() {
derived<int> a;
return 1;
}

C++ template function inside a non-template class [duplicate]

This question already has answers here:
How to create a template function within a class? (C++)
(4 answers)
Closed 7 years ago.
I am looking to start putting in templates in my c++ class code but I have come across a situation I have not experienced before. Basically I have a non-templates class but only 1 function in the class I need to be templated.
class example
{
public:
example();
~example();
<template T> templatefunction(T);
nontemplatefunction(string x);
};
Is this possible? If so, is it a common solution or am I looking at templates completely in error?
As people have noted in the comments, there's no problem doing so.
One aspect to watch out for is where to put the definition of the method templatefunction. For the time being (see the ISO cpp FAQ), you should consider placing it in the header file, which is different than what you'd probably do with the definition of the other methods. Thus you'd have example.hpp:
class example
{
public:
example();
~example();
template<typename T> void templatefunction(T);
void nontemplatefunction(string x);
};
template<typename T> void example::templatefunction(T)
{
}
and then example.cpp:
example::example(){}
void example::nontemplatefunction(string x)
{
}

C++, seeing objects in base template class from derived template class [duplicate]

This question already has answers here:
templates: parent class member variables not visible in inherited class
(3 answers)
Closed 8 years ago.
When I compile the following templated C++ code with GCC 4.8.3
template <typename dtype> class Base {
public:
dtype base;
dtype ceiling;
Base() { };
virtual ~Base() { };
};
template<typename dtype> class Building : public Base<dtype> {
public:
dtype wall;
Building(dtype concrete) {
Base<dtype>::base=concrete;
ceiling=concrete;
wall=concrete;
};
~Building() { };
};
int main (int argc, char* argv[]) {
Building<float>* building=new Building<float>(2.0);
std::cout << building->base << std::endl;
}
I get the error
error: ‘ceiling’ was not declared in this scope
ceiling=concrete;
So it appears that
Base<dtype>::base=concrete;
works, but
ceiling=concrete;
does not. Is there any way I can mogrify this templated code so that, in the derived class constructor I can just reference "ceiling" from the templated base class without having to clarify which class it is from?
Thanks in advance
You can use this->ceiling.

Template + Friend (a deadly combination) [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Making an undefined class as friend, and defining it later.
I have the following code
template<typename T>
class A
{
class B;
B b;
};
int main()
{
return 0;
}
The code doesn't emit any error because A is not instantiated. Am I right?
But have a look at the second code sample
template<typename T>
class A
{
protected:
class a
{
int x;
int y;
private:
friend class b;
};
template <typename U > class b
{
int z;
U y;
};
};
int main()
{
A<int> a;
return 0;
}
In this case A is instantiated but b is not. So the code shouldn't emit any error, right? But I get a redeclaration error in msvc++2008 professional edition. It compiles fine on gcc.
What could be the reason for the error?
Sorry everyone. After reading the comments and after seeing my original code I see that I made a mistake while typing the second code sample.
I missed the definition of the constructor and the statement a *object = new a; inside the constructor. Apologies. That means my code is exactly similar to the other code posted by the other user. But now I cannot delete my question now because of the existing answers.
Regarding you second code snippet ...
template<typename T>
class A
{
protected:
class a
{
int x;
int y;
private:
friend class b;
};
template <typename U > class b
{
int z;
U y;
};
};
int main()
{
A<int> a;
return 0;
}
... it is most probably invalid code, because a very similar code snippet posted by you earlier, in the SO question "Making an undefined class as friend, and defining it later", is invalid. But I'm not sure about this.
The difference wrt. your earlier question is only that in that other question the nested class a is used, hence, instantiated.
However, the redeclaration error that you get with MSVC 8.0 does not necessarily mean that that compiler recognizes the code as invalid standard C++. It might be a compiler bug that just by happenchance causes it to (probably) correctly identify the code as invalid. And it might just be that the above code, not using a, is valid…
So, it's pretty subtle, it's language lawyer stuff.
Best advice is to just stay well clear of these rather dark corners of the language.
EDIT: the earlier question was not Pavel's (but it's the same code); see comments.
Cheers & hth.,
Class a doesn't has an access to the members of the enclosing class according to the current Standard §11.8. But the Standard has a defect report to this. So some compilers works according to the original Standard, and the others according to the proposed resolution of the defect report.
MSVC requires the full template decl for friend template classes, MSDN has an example here, specifically the bottom example:
template <class T>
class X
{
private:
T* data;
void InitData(int seed) { data = new T(seed); }
public:
void print() { cout << *data << endl; }
template <class U> friend class Factory;
};
template <class U>
class Factory
{
public:
U* GetNewObject(int seed)
{
U* pu = new U;
pu->InitData(seed);
return pu;
}
}
so yours should declare:
template <typename U > friend class b;
The code doesn't emit any error
because A is not instantiated. Am I
right?
I am not sure, but I don't think so. A compiler which emits an error is also equally standards conformant as a compiler which does not.
The below quote along with the example that immediately follows is a proof of this to my mind
$14.6/7 - "[Note: if a template is
instantiated, errors will be diagnosed
according to the other rules in this
Standard. Exactly when these errors
are diagnosed is a quality of
implementation issue. ]"