This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
problem with template inheritance
This code doesn't compile in GCC:
template <typename T>
struct Base
{
public:
int x;
};
template <typename B>
struct Middle : public B
{
};
template <typename T>
struct Sub : public Middle<Base<T> >
{
public:
void F()
{
x=1; // error: ‘x’ was not declared in this scope
}
};
If either Base or Sub weren't template classes, it wouldn't complain. VC handles it.
Why?
Use this->x = 1; to tell the compiler that x is a (template-) dependent name.
Note: What GCC does ot fine according to the standard, MSVC is just a bit more tolerant.
Related
This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
Closed 5 years ago.
I'm having the weirdest error and I've no idea what I'm doing wrong.
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
B() { x = 3; } // Error: 'x' was not declared in this scope.
};
I don't understand how it's possible that I cannot see x from B, given that I'm inheriting A publicly.
At the same time, this code compiles:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {};
int main() {
B<false> b;
b.x = 4;
};
I'm compiling with g++ 7.0.1.
Edit: It seems that if I reference the full-name of x, the code compiles, as in:
B() { A<X>::x = 3; }
But why?
The compiler doesn't know how to find x. Use this->X and it will work.
At the time the compiler is doing its first pass over struct B, the template parameter is not known. By using the this pointer, you are deferring the name lookup until the second pass.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I try to build a partial template specialisation like the following (this does not make sense in this short form, but it is reduced to the problem):
#include <iostream>
#include <string>
template<class C> struct A {
int x;
std::basic_string<C> y;
};
template <class C, class T>
struct B { B(void) { std::cout << "default "; }; };
template<class C>
struct B<C, decltype(A<C>::x)> { B(void) { std::cout << "int "; }; };
template<class C>
struct B<C, decltype(A<C>::y)> { B(void) { std::cout << "string "; }; };
int main() {
B<char, int>{};
B<char, std::string>{};
B<wchar_t, std::wstring>{};
}
The VC++ compiler (v140 toolset) complains about the partial template specialisations saying that they are duplicates:
error C2953: 'B': class template has already been defined
My first question is: is the code above standard-conformant, ie should it compile?
If I switch the toolset to Visual Studio 2015 - Clang with Microsoft CodeGen (v140_clang_c2), it compiles and runs with the expected output "int string string", so my assumption is that the answer to the first question is "yes", because T is not a non-type.
Hence the second question: Is it possible to rephrase the code such that it removes the dependency on C which seems to make VC++ break?
And the third question: Is this a known problem of VC++ v140?
Thanks in advance,
Christoph
That's not the syntax for partial class template specialization. This is:
template <class T, class U>
class Traits { };
template <class T> // one template parameter
class Traits<T, decltype(A<T>::x)> { };
// ^^^^^^^^^^^^^^^^^^^^
template <class T>
class Traits<T, decltype(A<T>::y)> { };
You also have to make A::x and A::y accessible.
Aside from the missing class keyword and semicolon, this is an example of the explicit full class template specialization:
#include <iostream>
template<typename T> // primary template
struct is_void : std::false_type
{
};
template<> // explicit specialization for T = void
struct is_void<void> : std::true_type
{
};
This question already has answers here:
Why doesn't a derived template class have access to a base template class' identifiers?
(4 answers)
Closed 7 years ago.
The following code
template<int c>
struct Base
{
static const int a = c + 5;
};
template<int c>
struct Derived : Base<c>
{
static const int b = a + 5;
};
... fails to compile because a was not declared in this scope. Explicitly specifying Base<c>::a works, but logically this shouldn't be necessary because we're deriving from Base<c>. Is this intended behaviour (and why) or am I missing something?
template<int c>
struct Derived : Base<c>
{
static const int b = Base<c>::a + 5;
};
It really depends on compiler, but gcc requires it, it plays stupid when it comes to template classes
This question already has answers here:
templates: parent class member variables not visible in inherited class
(3 answers)
Closed 7 years ago.
The following code cannot compile - use of undeclared identifier. I use GCC and XCode for compilation.
Everything is in a single header file.
include "MyArray.h"
template <typename T>
class MyBase {
public:
MyBase();
virtual ~MyBase();
void addStuff(T* someStuff);
protected:
MyArray<T*> stuff;
};
template <typename T>
MyBase<T>::MyBase() {}
template <typename T>
MyBase<T>::~MyBase() {}
template <typename T>
void MyBase<T>::addStuff(T* someStuff) {
stuff.add(someStuff);
}
// ---------------------
template <typename T>
class MyDerived : public MyBase<T> {
public:
MyDerived();
virtual ~MyDerived();
virtual void doSomething();
};
template <typename T>
MyDerived<T>::MyDerived() {}
template <typename T>
MyDerived<T>::~MyDerived() {}
template <typename T>
void MyDerived<T>::doSomething() {
T* thingy = new T();
addStuff(thingy); //here's the compile error. addStuff is not declared.
}
Does anyone have an explanation?
Thanks in advance!
try
this->addStuff(thingy);
It's due to template inheritance. In such case you should mannualy specify using for base methods:
template <typename T>
MyDerived<T>::doSomething() {
using MyBase<T>::addStuff;
T* thingy = new T();
addStuff(thingy);
}
or do it by this pointer:
template <typename T>
MyDerived<T>::doSomething() {
T* thingy = new T();
this->addStuff(thingy);
}
There are several issues:
Missing semicolons after class definitions.
Missing type for doSomething method declaration/definition.
Missing type for definition of addStuff method.
After fixing that it seems to work.
Edit: As you have fixed the syntax errors and it still does not work. As others have suggested your compiler may require you to call the addStuff method with this-> prefix:
this->addStuff(thingy);
use this pointer to invoke the addStuff method i.e
this->addStuff(thingy);
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ Restrict Template Function
Is it possible to write a C++ template to check for a function's existence?
Is it possible to restrict the types for which a template may be instantiated
(that is, have a compiler error if I use template<type_not_allowed>)?
One way would be to provide no default implementation, and specialize your class template only on those types you wish to allow. For example:
#include <iostream>
using namespace std;
template<class X> class Gizmo
{
public:
Gizmo();
};
template<> Gizmo<int>::Gizmo()
{
}
int main()
{
Gizmo<float> gf; // ERROR: No specialization for Gizmo<float> results in a linking error
}
Make the constructor private in the illegal type:
template<typename T>
class Z
{
public:
Z() {}
};
template<>
class Z<int>
{
private:
Z();
};
Z<float> f; // OK
Z<int> i; // Compile time error.