I want to have a template that can access the protected method of it's typename parameter. How can I make that work?
For example:
class Foo{
...
protected:
int Bar();
}
template <class T> FooTempl{
...
int SomeMethod(T* ptr) { return ptr->Bar();};
...
}
The reason is that I want the method Foo::Bar() to be accessible to the template, but not to any other external caller. I hope there's some friend syntax there that can make it work...
An alternate to declaring FooTempl as a friend of Foo would be to have the former derive from the latter. In this case, since Foo is a base class for FooTempl, so FooTempl::SomeMethod would not need to have a Foo * parameter anymore.
class Foo
{
protected:
int Bar() { return 42; }
};
template <class T>
class FooTempl : public T
{
public:
int SomeMethod() { return T::Bar();}
};
int main()
{
FooTempl<Foo> bar;
bar.SomeMethod();
}
Which of these methods is more appropriate depends on your use case.
Add the following line into Foo:
template<typename T> friend class FooTempl;
Related
I'm pretty new about template programming and I could not find any related question, sorry if already exists a similar question.
I have my template class
template<class T>
class MyTemplate
{
public:
virtual void set(const T& val) { value_ = val; }
virtual T get() const { return value_; }
// other stuff
private:
T value_;
}
and a custom class
class Foo
{
void bar();
}
Then I declare a variable
MyTemplate<Foo> var;
How can I call the bar() method from var ?
To call bar() you need an instance of Foo somewhere. As already mentioned, you could use inheritance. I see that the question has been edited to add such a member. You can't call members of the template type directly. You could add a wrapper in the MyTemplate, for instance 'doBar()'. You could also (though it's not a good idea) expose the Foo member by making it public.
#include <iostream>
template<class T>
class MyTemplate
{
public:
void doBar() { value_.bar(); }
public:
T value_;
};
class Foo
{
public:
void bar();
};
void Foo::bar()
{
std::cout << "Foo::bar()\n";
}
int main()
{
MyTemplate<Foo> var;
var.doBar();
var.value_.bar();
}
BTW any other old timers reminded of Swaine's Flames in Dr Dobbs journal?
Let's say I have the following template class:
template<typename T>
class A
{
public:
// Lots of functions...
void someFunc(T obj)
{
// T must implement this function in order to be usable within class A.
obj.interfaceFunc();
}
};
This works fine, as the object I will use with the template class implements interfaceFunc().
However, if I pass a pointer to the template class then the compilation fails because the dereference syntax is incorrect. Because the template class contains a lot of other functions that I don't want to copy/paste into another partial specialisation if I can possibly help it, I have changed my class definition as follows:
template<typename T>
class A
{
public:
// Lots of functions...
virtual void virtualHelperFunction(T* obj)
{
// We should never be here in the base class.
assert(false);
}
void someFunc(T obj)
{
// Call the virtual function.
virtualHelperFunction(&obj);
}
};
// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
However, when virtualHelperFunction() is called, on an instance of B but when inside the someFunc() function of the parent A, it hits the assertion error.:
B<SomeObject> instance;
instance.someFunc(SomeObject()); // Assertion failure.
I've tried messing around with function pointers to solve this but I'm still fairly new to them, and the non-static pointer syntax confused me a bit. I'm assuming one could define a member pointer to the virtualHelperFunction() which is set to point to the base class version in A's constructor, but which is then overwritten in B's constructor to point to B's function. If so, would anyone be able to demonstrate the correct syntax to do this?
Thanks.
EDIT: If context is needed, the template class is an octree node which stores a hash table of type T. The interface function required is that the object can return a bounding box, in order for recursive insertion to function depending on whether the object's bounds intersect with the tree node's bounds.
https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.h
https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.tcc
This seems way too complicated. Why specialize the entire class if you just need one tiny bit specialized? All you need is a small utility that says "dereference this if it's a pointer, otherwise leave it alone". It could look like this:
template <typename T>
T& deref_if_pointer(T& t) { return t; }
template <typename T>
T& deref_if_pointer(T* t) { return *t; }
// ...
void someFunc(T obj) {
deref_if_pointer(obj).interfaceFunc();
}
You can easily extend deref_if_pointer to various smart pointers as well; just add another overload.
I'm not really sure what it is that you want to accomplish, so I'll have to guess. In what way does the following not satisfy your problem?
class A
{
public:
// Lots of functions...
void someFunc(T* obj)
{
// T must implement this function in order to be usable within class A.
obj->interfaceFunc();
}
void someFunc(T obj)
{
// T must implement this function in order to be usable within class A.
obj.interfaceFunc();
}
};
If you want to do it that way, then you need to take a reference instead of a pointer in the first partial specialization:
template<typename T>
class A
{
public:
// Lots of functions...
virtual void virtualHelperFunction(T* obj)
{
// We should never be here in the base class.
assert(false);
}
void someFunc(T obj)
{
// Call the virtual function.
virtualHelperFunction(&obj);
}
};
// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
// ...
virtual void virtualHelperFunction(T& obj)
{
obj.interfaceFunc();
}
};
// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
Your code doesn't compile. template<typename T*> is illegal and you do not have any partial specializations as you claim.
This works:
template<typename T>
class A
{
public:
// Lots of functions...
virtual void virtualHelperFunction(T* obj)
{
// We should never be here in the base class.
assert(false);
}
void someFunc(T obj)
{
// Call the virtual function.
virtualHelperFunction(&obj);
}
};
// Unspecialized template
template<typename T>
class B : public A<T>
{
public:
// ...
virtual void virtualHelperFunction(T* obj)
{
obj->interfaceFunc();
}
};
// Partial specialisation
template<typename T>
class B<T*> : public A<T*>
{
public:
// ...
virtual void virtualHelperFunction(T** obj)
{
(*obj)->interfaceFunc();
}
};
int main() {
B<SomeObject> instance1;
instance1.someFunc(SomeObject());
B<SomeObject*> instance2;
SomeObject x;
instance2.someFunc(&x);
}
I suspect I can't do this directly using a PIMPL pattern. Is it possible to have a smart pointer to a template class? I have not been able to compile by turning knobs on the shared_ptr declaration.
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
Under Visual Studio 2008: "error C2065: 'T' : undeclared identifier". I receive a similar error under GCC. If I un-parameterize FooImpl (so that FooTempl inherits from FooImpl), the code will compile.
I suspect I can't paramaterize the smart pointer, but I could be wrong.
EDIT: The second Visual Studio error is more telling: "error C3203: 'FooImpl' : unspecialized class template can't be used as a template argument for template parameter 'T', expected a real type"
Jeff
I'm not entirely certain what you are trying to accomplish, but does this help?
Try 1:
// ============Foo.h ============
// Forward declare the implementation
template <typename T> class FooImpl;
template<class C>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<C> > m_impl;
};
// ============FooImpl.h ============
template <typename T>
class FooImpl
{
...
};
Try 2:
// ============Foo.h ============
// Forward declare the implementation
class FooImplBase;
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImplBase > m_impl;
};
// ============FooImpl.h ============
class FooImplBase {
public:
virtual void AnAPI();
virtual int AnotherAPI();
};
template <typename T>
class FooImpl : public FooImplBase
{
...
};
The code you have posted cannot compile since T does not mean anything in the context of Foo. The compiler expects a type called T here which does not exist there... Not entirely sure what you are trying to accomplish, but wouldn't the following solve your problem?
// ============Foo.h ============
class FooImplBase {
virtual void WhateverFooImplIsSupposedToDo() = 0;
};
template <typename T> class FooImpl : public FooImplBase {
T mInstance;
public:
FooImpl(T const & pInstance) : mInstance(pInstance) {}
virtual void WhateverFooImplIsSupposedToDo()
{
// implementation which deals with instances of T
}
};
class Foo
{
public:
Foo getInstance(const string& fooType) {
// use m_impl->WhateverFooImplIsSupposedToDo...
}
template < class T >
Foo( T const & pInstance ) : m_impl(new FooImpl<T>(pInstance)) {}
private:
shared_ptr< FooImplBase > m_impl;
};
You're doing it right, just make sure T is defined. This compiles for me on MSVC++ 2010:
#include <memory>
using namespace std;
template<class T>
class Blah {
public:
Blah() { }
};
class Foo {
public:
shared_ptr<Blah<int>> ptr;
Foo() : ptr(new Blah<int>()) { }
};
If you're on an older compiler that hasn't incorporated this feature of C++11 yet, change
shared_ptr<Blah<int>> ptr;
To
shared_ptr<Blah<int> > ptr;
So the compiler doesn't think the >> is a right shift. C++11 doesn't have this problem though.
I don't know in advance I am going to have a Blah, only a Blah.
From the language point of view, Blah<T> is meaningless because T doesn't exist. Depending on what you're exactly trying to do, you can
make Foo a template, too, so that you can declare a template parameter T:
template<typename T>
class Foo
{
public:
Foo getInstance(const string& fooType);
...
private:
shared_ptr< FooImpl<T> > m_impl;
};
which 'fixes' the choice of T when you declare a variable of type Foo<T>;
or make FooImpl explicitly derive from a common base:
class FooBase {
// need to define the interface here
};
// this is a class definition whereas previously you only needed a declaration
template<typename T>
class FooImpl: public FooBase {
// definition here
};
class Foo
{
public:
Foo getInstance(const string& fooType);
// we needed the definition of FooImpl for this member
// in addition this member is quite obviously a template
template<typename T>
void
set(FooImpl<T> const& foo)
{
m_impl.reset(new FooImpl<T>(foo));
}
// not a member template!
void
use()
{
// any use of m_impl will be through the FooBase interface
}
private:
shared_ptr<FooBase> m_impl;
};
where for a given Foo instance any kind of FooImpl<T> can be set dynamically and then used through the FooBase interface. This is a kind of type erasure as it's called in the C++ world.
We can use templates to write a generic smart pointer class. Following C++ code demonstrates the same. We don't need to call delete 'ptr', when the object 'ptr' goes out of scope, destructor for it is automatically.
#include<iostream>
using namespace std;
// A generic smart pointer class
template <class T>
class SmartPtr
{
T *ptr; // Actual pointer
public:
// Constructor
explicit SmartPtr(T *p = NULL) { ptr = p; }
// Destructor
~SmartPtr() {
cout <<"Destructor called" << endl;
delete(ptr);
}
// Overloading dereferncing operator
T & operator * () { return *ptr; }
// Overloding arrow operator so that members of T can be accessed
// like a pointer (useful if T represents a class or struct or
// union type)
T * operator -> () { return ptr; }
};
int main()
{
SmartPtr<int> ptr(new int()); // Here we can create any data type pointer just like 'int'
*ptr = 20;
cout << *ptr;
return 0;
}
out put:
20
Destructor called
I have a template class for which I need to access a protected member function of the template parameter, like this:
class Foo
{
protected:
void foo() {}
};
template<typename T>
class Bar
{
public:
static void bar(T& self){self.foo();}
};
...
Foo f;
Bar<Foo>::bar(f);
My problem is getting access to the protected method. I tried putting a friend class T into Bar, but that doesn't seem to be allowed in c++ (edit: and wouldn't solve my problem anyways, so it seemd). I tried letting Bar inherit from T (template<typename T> class Bar: public T (could have used private inheritance, but the public interface of Bar is not terribly important, since the class itself is internal only)), but that didn't allow for access of foo() either. So how do I get access to the foo() method?
Edit:
Foo should not need to know Bar<Foo>, since there are quite a lot Bar classes. I can however make other changes to Foo (without changing the public interface of course).
OK, this is a "rot in hell" hack. You can abuse the fact that you can form pointers-to-members pointing to protected base members from a derived class.
class Foo
{
protected:
void foo() {}
};
// Helper template to bypass protected access control
// for a member function called foo, taking no parameters
// and returning void.
template<typename T>
struct Unprotect : public T
{
typedef void (T::*FooPtr)();
static FooPtr GetFooPtr()
{
return &Unprotect::foo;
}
};
template<typename T>
class Bar
{
public:
static void bar(T& self){(self.*Unprotect<Foo>::GetFooPtr())();}
};
int main()
{
Foo f;
Bar<Foo>::bar(f);
}
You did your friend declaration in the wrong direction. If Bar says Foo is it's friend, that means Foo gets access to Bar's private data. For Bar to get access to Foo's private data, Foo has to say Bar is its friend.
template<typename T>
class Bar
{
public:
static void bar(T& self){self.foo();}
};
class Foo
{
protected:
void foo() {}
friend class Bar<Foo>;
};
void main()
{
Foo f;
Bar<Foo>::bar(f);
}
If you want to access a protected member a derived class of this, you can do it with the using keyword:
class A
{
protected:
void i_am_protected () {}
};
template <class T>
class B : public T
{
using T::i_am_protected;
void call_me ()
{
i_am_protected(); // OK.
this->i_am_protected(); // This compiles without the keyword.
}
};
If you need B to access a protected member of A when an object is passed to B, you need to declare B as a friend of A:
class A
{
template <class T>
friend
class B;
protected:
void i_am_protected () {}
};
template <class T>
class B : public T
{
void call_me (T& obj)
{
obj.i_am_protected(); // OK.
}
};
I have two classes that depend on each other:
class Foo; //forward declaration
template <typename T>
class Bar {
public:
Foo* foo_ptr;
void DoSomething() {
foo_ptr->DoSomething();
}
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};
When I compile it in g++, it was giving error of "Invalid use of incomplete type", but it was compiled nicely in MSVC 10.
Is it possible to solve this problem while keeping the declaration and definition in one header file? (no cpp files)
If this is not allowed in the standard, so is this one of the MSVC "bug" or "feature"?
Yes, just move the method definitions out of the class definition:
class Foo; //forward declaration
template <typename T>
class Bar {
public:
Foo* foo_ptr;
void DoSomething();
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};
// Don't forget to make the function inline or you'll end up
// with multiple definitions
template <typename T>
inline void Bar<T>::DoSomething() {
foo_ptr->DoSomething();
}
See this page:
What is the best way to deal with co-dependent classes in C++?
It should clear up the problem and provides a couple nice solutions.
It works when you replace Foo* foo_ptr; by the template parameter T so that you get T* foo_ptr;. In this foo_ptr does not necessarily have to be a pointer or be predefined.
template <typename T>
class Bar {
public:
T foo;
void DoSomething() {
foo.DoSomething();
}
};
class Foo {
public:
Bar<Foo>* bar_ptr;
void DoSomething() {
bar_ptr->DoSomething();
}
};