In the following program "Here" is printed:
#include <iostream>
class Base
{
static bool temp;
static bool initTemp()
{std::cout<<"Here\n";return true;}
};
bool Base::temp = Base::initTemp();
class Derived : public Base
{};
int main() {int a;std::cin>>a;}
In the following program "Here" is not printed:
#include <iostream>
template <class T>
class Base
{
static bool temp;
static bool initTemp()
{std::cout<<"Here\n";return true;}
};
template <class T>
bool Base<T>::temp = Base<T>::initTemp();
class Derived : public Base<int>
{};
int main() {int a;std::cin>>a;}
In both cases Base is never referenced. The only difference is that in the second case it is a template class. Can anyone explain to me why this behavior occurs. I am using VS 2012.
In both cases Base is never referenced.
And that is precisely the reason why you see nothing being printed to the standard output.
The definition of a class template's static data member does not get instantiated unless you use that data member; like member functions, the definitions of static data members of a class template are instantiated on demand.
This is specified in paragraph 14.7.1/1 of the C++11 Standard:
[...] The implicit instantiation of a class template specialization causes the implicit
instantiation of the declarations, but not of the definitions or default arguments, of the class member functions,
member classes, scoped member enumerations, static data members and member templates. [...]
Since your client code never refers to Base<>::temp, there is no need to construct and initialize it.
As a side note, this signature:
void main()
Is not valid (standard) C++. If you want to write portable code, the return type of main() should always be int.
In the first case, you don't instantiate Base, but you do call the static function:
bool Base::temp = Base::initTemp();
In the second case, you never instantiate the template:
template <class T>
bool Base<T>::temp = Base<T>::initTemp();
You can explicitly instantiate the Base class template, as with:
template class Base<int>;
And then you will see "Here" printed.
You cannot create variable of undefined class, which you seem to do with line:
template <class T>
bool Base<T>::temp = Base<T>::initTemp();
You cannot allocate variable of undefined type. What you need is write something like:
Base<int>::temp = value;
of cause there will be different variable allocated for each type provided, so you cannot have common static variable for a template class. You'll have separate variable for each type you instantiate your template instead.
To downvoters here is complete example:
#include <iostream>
template<class T>
class X
{
public:
static int v;
};
template<class T>
int X<T>::v = 0;
int main()
{
X<int>::v = 3;
X<char>::v = 2;
using namespace std;
cout << X<char>::v << endl << X<int>::v;
}
It prints 2 3 which means you cannot have single variable for all classes you'll instantiate your template.
Related
The STL <memory> header (MSVC implementation) contains a class called:
template <class _Ty> class _Ref_count_obj2 : public _Ref_count_base
This class has a member:
union {
_Wrap<_Ty> _Storage;
};
where _Wrap is defined as:
template <class _Ty>
struct _Wrap {
_Ty _Value; // workaround for "T^ is not allowed in a union"
};
From my understanding, this code is designed to hold an object of type _Ty following its construction via the new operator. However I can't figure out why this was done; it seems like using a struct instead of a struct inside a union would work just as well.
Can anyone explain the reasoning behind this? Also, can anyone explain the comment in the _Wrap definition?
First, embedding the _Storage member in a union will prevent default destruction of that object (which is, more than likely, a non-trivial type); this appears to be essential, as the class involved is a reference counter. (By default, unions have a deleted destructor; see, for example: Is a Union Member's Destructor Called .)
Second, using an anonymous union 'moves' the _Storage identifier into the enclosing scope, thus removing any need for X.-style notation (if the union were to be named X). From cppreference:
Members of an anonymous union are injected in the enclosing scope (and
must not conflict with other names declared there).
Last, the need to wrap the union's member into a templated structure is so that the class will work with reference types, which are not allowed in unions. To check this last part out, try the following code with the commented-out lines made active:
template <class _Ty>
struct _Wrap {
_Ty _Value; // workaround for "T^ is not allowed in a union"
};
template<class T>
class bob {
public:
bob(T t) : uncle{t}//, aunty(t)
{
}
private:
union {
_Wrap<T> uncle;
};
// union {
// T aunty;
// };
};
int main()
{
int i = 42;
bob<int&> b{ i }; // Note: Template uses a REFERENCE type
return 0;
}
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Closed 8 years ago.
I am developing a library at my work and I have designed a complicated inheritance that includes template classes and deriving from them.
My problem is that a base template class has virtual overloaded operator that takes 2 arguments and returns some value. In base class this operator is implemented and most of derived classes does not reimplement this operator.
Some other class uses derived classes for some work and make use of their operator member function. Everything works just fine as long as derived class has no other overloaded operator, even with different number of arguments. If one does then the base class operator is not accessible using it as object() because compiler can not find proper member function (complains about argument count missmatch).
It does not matter wether default template arguments for base class was specified or not. Also order of definitions of derived classes does not change which operator cause the problem (it is always SpecificDerived class).
Below I present simplified problem.
[EDIT] Example was simplified
Base Class definition:
template<class ret_t>
class TemplateBase2
{
public:
virtual ~TemplateBase2()
{
}
virtual ret_t memberFunc(ret_t x)
{
return x * 2;
}
};
User of derived classes definition:
template <class worker, class ret_t>
ret_t gobble(worker w, float f)
{
return w.memberFunc((ret_t)f);
}
Derived class:
class SpecificDerived2: public TemplateBase2<float>
{
public:
float memberFunc()
{
return 3.14;
}
};
Main function:
#include <iostream>
#include "TemplateBase2.h"
using namespace std;
int main()
{
SpecificDerived2 sd2;
cout << "sd2: " << gobble<SpecificDerived2, float>(sd2, 3.14f) << endl;
return 0;
}
Compiler exits with error claiming that there is no matching function for call to 'SpecificDerived2::memberFunc(float)' from gobble function. Problem exists only when either derived or base class has two overloaded functions of the same name, but different arguments.
I am using MinGW32 4.8.1 with c++11 support.
When a class template derives from a base class template, the base members are not visible in the derived class template definition. (This makes sense; until you specialize, there is no class, and so there are no members. Explicit specializations can always change the meaning of any given template class.)
In other words, the base template member names are dependent names and not looked up in the first phase of template definition lookup.
There are three ways to get around this. Let's make it concrete with a quick example:
template <typename T> struct Foo
{
int data;
using type = const T &;
void gobble() const;
template <int N> void befuddle();
};
template <typename T> struct X : Foo<T> { /* ... */ };
Now in the context of the derived class template definition, you can...
Qualify the name:
Foo<T>::data = 10;
typename Foo<T>::type x;
Foo<T>::gobble();
Foo<T>::template befuddle<10>();
Use this:
this->data = 10;
this->gobble();
this->template befuddle<10>();
(This doesn't work for type names names.)
Use a using declaration:
using Foo<T>::data;
using Foo<T>::gobble;
using type = typename Foo<T>::type;
data = 10;
gobble();
(This doesn't work for template names.)
Update: After your edit, the question is entirely different. Templates don't play a role at all here, since the problem doesn't contain templates, only classes. What's happening is the simple fact that member functions in a derived class hide member functions of the same name in base classes, so the presence of SpecificDerived2::memberFunc hides the base member function. The simple solution is to unhide base members of the same name with a using declaration:
class SpecificDerived2 : public TemplateBase2<float>
{
public:
using TemplateBase2<float>::memberFunc;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
float memberFunc()
{
return 3.14;
}
};
I have a c++ template class that has a nested class inside, something like:
template<int d>
class Outer_t
{
public:
class Inner;
Inner i;
};
template<int d>
class Outer_t<d>::Inner
{
public:
float x;
};
int main ()
{
Outer_t<3> o_t; // 3 or any arbitrary int
o_t.i.x = 1.0;
return 0;
}
This compiles without any problems. However, as soon as I declare a similar non-template class, something like this:
class Outer_1
{
public:
class Inner;
Inner i;
};
class Outer_1::Inner
{
public:
float x;
};
int main ()
{
Outer_1 o1;
o1.i.x = 1.0;
return 0;
}
I start getting the following error (I'm using gcc 4.6.3): "error: field ‘i’ has incomplete type". I know that I can remedy this by simply defining the inner class inline, inside the outer class:
class Outer_2
{
public:
class Inner {
public:
float x;
};
Inner i;
};
This will compile, but I would like to avoid defining the nested class inline. So I have two questions: what is the reason for this apparently odd discrepancy between a template and non-template nested class declaration? And is there an elegant way to declare and use the nester class inside the outer class, while avoiding defining it inline, much in the same style as the template class? Thanks in advance for your help!
Why the compilation error?
The compiler needs to know the size of the member variable types in order to do object layout. For Outer_1, because Inner is simply a forward declaration, we don't know its size. Hence the compilation error. For Outer_2 however, the definition is inline, so we know the size of it by the time we get to the member variable of type Inner.
Why do templates get a pass?
Class templates, on the other hand, don't get defined until template instantiation occurs. In your example, the implicit instantiation occurs in main. At that point, the definition of Inner is complete and therefore its size is known. We can see that this is the case by using explicit instantiation before the definition of Inner.
template<int d>
class Outer_t
{
public:
class Inner;
Inner i;
};
template class Outer_t<3>; // explicit instantation
template<int d>
class Outer_t<d>::Inner
{
public:
float x;
};
int main ()
{
Outer_t<3> o_t; // 3 or any arbitrary int
o_t.i.x = 1.0;
return 0;
}
Clang produces the following error:
a.cc:7:11: error: implicit instantiation of undefined member 'Outer_t<3>::Inner'
Inner i;
^
a.cc:10:16: note: in instantiation of template class 'Outer_t<3>' requested here
template class Outer_t<3>;
^
a.cc:5:11: note: member is declared here
class Inner;
^
The Solution
If you want to pull out the definition of the nested class, my suggested solution is to have it templatized just like Outer_t, but provide an alias for your convenience.
template <typename Dummy = void>
class Outer_1_Impl {
public:
class Inner;
Inner i;
};
template <typename Dummy>
class Outer_1_Impl<Dummy>::Inner {
public:
float x;
};
using Outer_1 = Outer_1_Impl<>;
int main () {
Outer_1 o1;
o1.i.x = 1.0;
}
You can only have non-static members in an object which have a complete definition when defining the class. In your non-template example, Outer_1::Inner is clearly not complete as it is only declared so far. The only way to create a member of Inner is, indeed, to define it like it is done for Outer_2.
Now, why does the problem not arise when using a class template? The answer is: when you are instantiating Outer_t in main(), there actually is a complete definition of Outer_t<T>::Inner accessible! ... and before instantiating Outer_t<T> with some type T the definition of Outer_t isn't really needed.
It looks like c is a function that takes "d" as argument. I know that :: is used to indicated name spaces and their sub-name spaces. But what A<B> mean? I know that B is class. I also know templates can be used for classes, functions and structures. But in this example it looks like we use a template for a name space.
It means you have a class template called A accepting a type parameter, and you instantiate that template with type B as its type argument.
That class template, in turn, defines either (1) a static member callable object c (could be a regular function) which accepts an object of a type to which a string literal is convertible, or (2) a type alias c for a type which is constructible from a string literal (and in that case you are constructing a temporary of that type).
In both cases, you access an entity defined inside class template A by using the same scope resolution operator (::) that you would use to access an entity defined inside a namespace (after all, both classes and namespaces define a scope).
As an example of (1) (live example):
#include <iostream>
struct B { };
template<typename T>
struct A
{
static void c(const char* s) { std::cout << s; }
};
int main()
{
A<B>::c("d");
}
As another example of (1) using a callable object rather than a function (live example):
#include <iostream>
struct B { void operator () (const char* c) { std::cout << c; } };
template<typename T>
struct A
{
static T c;
};
template<typename T>
T A<T>::c;
int main()
{
A<B>::c("d");
}
As an example of (2) (live example):
#include <iostream>
struct B { B(const char* s) { std::cout << s; } };
template<typename T>
struct A
{
typedef T c;
};
int main()
{
A<B>::c("d");
}
The scope resolution operator :: is used both with namespaces and fully qualified members.
In your example, c() looks like a static method exposed by the A<B> template class. Static members have to be fully qualified when accessed outside of their class.
As others rightfully point out, c can also be a callable static member (e.g. an instance of a type that overrides operator()(const char *)), or an alias to a type constructible from a const char *, or a public class or struct nested in A<B> that is constructible from a const char *.
(In the latter two cases, the constructor of that type is called only for its side-effects, since the created instance is not stored anywhere.)
I understand that the member names of a base-class template are hidden within the scope of a derived class, and therefore must be accessed using this->foo or Base<T>::foo. However, I recall that C++ also allows you to use the using keyword, which can come in handy in a derived-class function which frequently accesses a base-class variable. So, in order to avoid cluttering up the function with this-> everywhere, I'd like to use the using keyword.
I know I've done this before, but for whatever reason I can't get it to work now. I'm probably just doing something stupid, but the following code won't compile:
template <class T>
struct Base
{
int x;
};
template <class T>
struct Derived : public Base<T>
{
void dosomething()
{
using Base<T>::x; // gives compiler error
x = 0;
}
};
int main()
{
Derived<int> d;
}
The error, (with GCC 4.3) is: error: ‘Base<T>’ is not a namespace
Why doesn't this work?
It doesn't work because C++ language has no such feature and never had. A using-declaration for a class member must be a member declaration. This means that you can only use in class scope, but never in local scope. This all has absolutely nothing to do with templates.
In other words, you can place your using-declaration into class scope
struct Derived : public Base<T> {
...
using Base<T>::x;
...
};
but you can't have it inside a function.
Using-declarations for namespace members can be placed in local scope, but using-declarations for class members cannot be. This is why the error message complains about Base<T> not being a namespace.
Outside class scope (if you are in a block etc), you can only name namespace members in a using declaration.
If you don't want to place that using declaration into the scope of Derived (which IMO is the favorable solution), your other option is to use a reference
int &x = this->x;
x = 0;
It should be noted that this is semantically different, because it
Forces a definition to exist for Base<T>::x, which might not be the case for static const data members
Forces Base<T>::x to be of type int& or be convertible to type int&.
Otherwise, if you want to avoid using this-> all again, I don't see other options.
template <class T>
struct Base
{
int x;
};
template <class T>
struct Derived : public Base<T>
{
using Base<T>::x;
void dosomething()
{
x = 0;
}
};
int main()
{
Derived<int> d;
}
As others said, it is working only class scope.