how to call methods of defined classes from within template class methods - c++

How should I call a method within a defined class from a template class method?
Below is my scenario -
Template Class
template <class T>
class TC {
void myTemplateMethod() {
T.myMethod(); //can I call like this ?
}
};
Defined Class
class tdef {
void myMethod() {
//does something
}
};
Main
int main() {
TC<tdef> tobj;
tobj.myTemplateMethod(); //can I call tdef.myMethod() like this?
}
Just to note, that I have debugged a code like this and have found that tdef.myMethod() does not work when called like this. Also are there any chances that some exceptions are not handled while calling tdef.myMethod() from within Template class method?
-Somnath

That's a non-static member function, so it can only be called on an instance. Templates don't change that fact.
T t;
t.myMethod();
or if the function were static:
T::myMethod();

Related

How can I easily redirect a Base method to an identical Derived class method?

In working with a framework (Godot) that uses a register_method(<name>, <pointer_to_method>) to register a c++ method to a scripting API.
this method however doesn't support pointer to template classes.
So in the example:
static void _register_methods() {
register_method("my_method", &TMyClass::my_method); // this fails
// ^ template class
register_method("my_method", &MyClass::my_method); // this works
// ^ normal class
}
I have a template class TExample and an Example that extends the template class. The methods declarations and method definitions are all inside the TExample (however the methods are registered in Example).
So when I do:
register_method("my_method", &Example::my_method); // this fails because it is referencing the method of the parent class (template).
What I've found that works is redirecting the methods to "local" methods.
class Example : TExample<...>
{
public:
void my_method() {
TExample::my_method();
}
static void _register_methods() {
register_method("my_method", &Example::my_method); // this works
}
}
But imagine I have like 50 methods every time I want to create a new class from the template I need to redirect 50 methods. is there a shortcut to do this?!
Not sure what you mean by "this fails".
It just works, look (live demo):
template<class T>
class TExample {
public:
void my_method() {}
};
class Example : TExample<int> {
template<class U>
static void register_method(U u) {
}
public:
static void register_methods() {
register_method(&Example::my_method); // it works
register_method(&TExample::my_method); // this also works
}
};
int main()
{
Example ex;
ex.register_methods();
}
Now if you want to access my_method() from outside the class, then you should inherit publicly:
class Example : public TExample<...>
{
Then Example::my_method() will also work outside.
Note: TExample is not a template class, but a class template. However, in the context of a template instantiation (inside the definition of Example) the template arguments are substituted automatically.
Since template classes will be created for the types you are using you should mention the type also.
register_method("my_method", &TMyClass<Type>::my_method);
What about using a lambda ?
Does:
register_method("my_method", [&obj](*whateverParam*) { obj.templateMethod(*whateverParam*); } );
work?
(assuming obj contains the actual method, but that could be replaced by any instance containing the method).

C++/(Qt) pointer to any object with specific method

How do I do to call a specific method present on all classes from an other (TranslationManager) class ?
I simplified a lot the code. I just want to call the setTranslationText of any class from TranslationManager.
These are to take in consideration:
All classes have a setTranslationText method
We should call setTranslationText of any class from TranslationManager by using the pointer to the class
class Interface
{
...
public:
void setTranslationText(QString translatedString);
}
class AnyOtherInterface
{
...
public:
void setTranslationText(QString translatedString);
}
...
…
Translationmanager::Translationmanager(){
AnyClass = Interface; // Pointer to Interface Class
AnyClass->setTranslatioNText("Text");
AnyClass = AnyOtherInterface; // Pointer to AnyOtherInterface Class
AnyClass->setTranslatioNText("AnotherText");
}
…
You could use a template
template <typename T>
void setTranslationText(T* t, const QString &translatedString)
{
t->setTranslationText(translatedString);
}
That way you wouldn't need an interface class just to inherit for this one (or however many) methods. Then the template would only compile if for a given class instantiation they had a setTranslationText method defined. The way you'd use it is
Translationmanager::Translationmanager()
{
setTranslationText(Interface, "Text"); // Pointer to Interface Class
setTranslationText(AnyOtherInterface, "AnotherText"); // Pointer to AnyOtherInterface Class
}
Adding to Cory's answer: If you're using C strings to initialize QString, you shouldn't depend on the implicit conversion - instead, make your use case explicit:
template <typename T>
void setTranslationText(T* t, const char *translatedString) {
t->setTranslationText(QString::fromUtf8(translatedString));
}
I wasn't precise about what I wanted. I finally found the best solution to my problem: callback.
Solution found on: C++ class member callback simple examples
std::vector<std::function<void(std::string,std::string)>> callbacks;
template<class T> void addTranslationText(T* const object, void(T::* const mf)(std::string,std::string)){
using namespace std::placeholders;
callbacks.emplace_back(std::bind(mf, object, _1, _2));
}
...
// Call callback
callbacks.at(0)(std::string("arg1"), std::string("arg2"));

Mock base class method in chain template inheritance

Suppose you have a template class like the one below which inherit from a wide range of other classes.
template<typename T>
class Generic : public T
{
//implementation
}
It's not allowed to modify class Generic. To overcome this I write a wrapper to this class which inherit a specific type of Generic class. Inside this class I mocked a virtual method from class A
class Wrapper: public Generic<A>
{
MOCK_METHOD2(methodFromA,void(int a,int b));
}
Then I write a test which looks like this. The problem is that I get segmentation fault when EXPECT_CALL is invoked. Calling other methods from class A works as expected.
TEST(classA, TC0)
{
std::shared_ptr<Wrapper> wrapper = std::dynamic_pointer_cast<Wrapper>(functionReturnPointerToA())
if(wrapper)
{
EXPECT_EQ(1,methodFromAwhichReturns1()); //it works
EXPECT_CALL(*wrapper,methodFromA(_,_); //segmentation fault
}
}
I also tried template specialization but this doesn't seems to works either since MOCK_METHOD is an preprocessor directive
template <> inline Wrapper<A>::MOCK_METHOD2(methodFromA,void(int a,int b));

Overriding C++ function based on conditional

So I've used C for a long time and Java, too, but I'm not that familiar with C++. The situation is that we have:
base class template 1 -> base class template 2 -> several relevant subclasses
Currently all of the final subclasses inherit a member function from class 1, but we need to change the behavior of this function only in one of the subclasses, and only if a variable elsewhere in the code is set, and otherwise run the function as defined in class 1. Is there a way to do this without slotting the entire function definition on the other side of an if-else? I've looked at SFINAE/enable-if, but that's used for type-based decisions, not simple conditionals like this.
If I'm missing anything easy or dumb please let me know.
Some pseudocode might help:
template <class Face> class Publisher {
virtual void publish(...) {
// do stuff
}
}
template <class NewsType> class NewsPublisher : public Publisher<OnlineFace> {
// constructors, destructors...
}
class MagazinePublisher : public NewsPublisher<Sports> {
void publish(...) {
if(that.theOther() == value) {
// do different stuff
} else {
// do whatever would have been done without this override here
}
}
}
According to your example you can simply call the base class implementation explicitly:
class MagazinePublisher : public NewsPublisher<Sports> {
void publish(...) {
if(that.theOther() == value) {
// do different stuff
} else {
// call the base class implementation, as this function would not
// have been overridden:
NewsPublisher<Sports>::publish(...);
// ^^^^^^^^^^^^^^^^^^^^^^^
}
}
}
Well, I suppose your actual base class function publish() is declared as virtual member.
Also since your sample is just pseudo code and I couldn't really test it, you might need to add which publish() implementation should be used in the NewsPublisher<T> class:
template <class NewsType> class NewsPublisher : public Publisher<OnlineFace> {
public:
// constructors, destructors...
using Publisher<OnlineFace>::publish(); // <<<<<<<<<<<<<
}

How to obtain similar result as virtual function template c++

Here's my issue, I'm trying to create a base class which can get a reference to a queue member in a derived class. I have two template functions in my base class :
class Base
{
template<TYPE type>
virtual void foo(std::queue<TYPE>*& typeQueue) //I know virtual isn't allowed
{
//do nothing as it's general case
}
template<typename TYPE>
void bar(TYPE type)
{
std::queue<TYPE>* typeQueue;
foo(typeQueue);
//... do some stuff with type
}
}
and a derived class which would theoretically be able to specialize the function foo for any types
class Derived : public Base
{
public:
template<>
void foo<int>(std::queue<int>*& m_integerQueue)
{
integerQueue= &m_integerQueue;
}
template<>
void foo<double>(std::queue<double>*& doubleQueue)
{
doubleQueue = &m_doubleQueue;
}
private:
std::queue<int> m_integerQueue;
std::queue<double> m_doubleQueue;
}
code above is more of about an ideology then a code to take word for word, I'd like the function bar to call the according function foo in derived class based on the type specified when bar is called. Of course this solution isn't working and the problem here is that we can't make template functions virtual.
I'm not sure if it's an error of design, but that's the general idea and I couldn't find an appropriate solution anywhere so I posted my own question here.
EDITED to make my problem clear