I have the following class:
template <class T>
class BeliefSet : public Belief<T>
{
private:
std::vector<T> m_Facts;
public:
void RemoveFact(const T Fact)
{
m_Facts.remove(Fact);
}
};
This works fine. However, I want to derive another class from BeliefSet and override this method RemoveFact(), thus I changed the code shown above to the following:
/* Rest of this class has not been changed. */
virtual void RemoveFact(const T Fact)
{
m_Facts.remove(Fact);
}
Now as soon as I compile I get this error:
error C2039: 'remove': is not a member of 'std::vector<std::string,std::allocator<_Ty>>'
Any ideas what I am doing wrong here?
This works fine.
No, it doesn't. std::vector has no member function remove(). However, class template member functions aren't eagerly instantiated. It's likely that you simply never invoked RemoveFact(), so you never had to run into this problem. This "lazy" instantiation is very important - it lets you write and use class templates that have conditionally valid operators without writing loads of SFINAE junk (e.g. I can use std::map fine with non-default-constructive value types, I just can't use operator[]).
When you made the function virtual, as you as inherit from it, it is likely that your compiler attempted to instantiate the function at that point (it is unspecified whether an implementation does so - yours apparently does). Since this function is ill-formed, you get the error via the virtual function instantiation instead of normal function instantiation.
Either way, the function is broken and you want:
void RemoveFact(const T& Fact)
{
m_Facts.erase(
std::remove(m_Facts.begin(), m_Facts.end(), Fact),
m_Facts.end());
}
Related
I want to have classes with a static data member knowing the class's complete size. This is for storing singleton instances, in case you want to know the actual use case of this.
In my naive implementation of this feature, I wanted to use a mixin class to add the special data member to my class. The mixin class would have to know the complete class (in order to know the complete class's size), so I implement it using the Curiously Recurring Template Pattern, a little bit like this:
template<class ObjectType>
class SingletonOf
{
static inline /* some type same size as ObjectType */ instance_memory;
public:
void *operator new(std::size_t)
{
return &instance_memory;
}
void operator delete(void *)
{
}
};
class foo : public SingletonOf<foo> // CRTP used here, to let SingletonOf know foo
{
// foo data members...
// foo member functions...
};
void bar() {
foo *p = new foo; // calls SingletonOf<foo>::operator new and returns the instance memory
}
Cute, right? Well, I learned that the following in C++20 is ill-formed (note: in all the code samples below, the class foo and the function bar() do not change. Also I will not keep writing the empty definition of SingletonOf::operator delete, because you can remember that it's there):
template<class ObjectType>
class SingletonOf
{
static char inline instance_memory[sizeof(ObjectType)]; // syntax error: incomplete type
public:
void *operator new(std::size_t) { return instance_memory; }
...
Now, we will all agree the reason why that is ill-formed - and I am not complaining, just informing - is that ObjectType is foo, and until the closing brace of foo, foo is an incomplete type. And, obviously, sizeof cannot be called on incomplete types. So, I am fine with that. However, the following using a nested class-template does work - at least according to clang++ in c++20 mode, I think?
template<class ObjectType>
class SingletonOf
{
template<class CompleteObjectType>
struct InstanceMemory
{
static char inline instance_memory[sizeof(CompleteObjectType)];
};
public:
void *operator new(std::size_t) {
return InstanceMemory<ObjectType>::instance_memory;
}
...
Now my question is: why does that work? Or, let's start with the more fundamental question: does that work, actually? As of this writing, just to be clear, I have not verified that bar() actually calls the intended operator new and returns the foo-sized instance memory. Probably, should do that. But I'm busy. What I do know at this time, is that my clang++ in c++20 mode compiles it. This compilation includes compiling the function bar(), which allows me to be certain it instantiates the template. So that is to back up my contention that the compiler is accepting it. There are no errors or warnings give, just an output object file.
If I am right that this second code is well-formed, then it looks like ObjectType (= foo) in the body of operator new in the second code sample, is considered a complete type. How did that happen?
This isn’t really any different from having InstanceMemory defined in a namespace: until it is instantiated, its template argument need not be complete. This separation works because it removes the presumption that you should be able to use decltype(SingletonOf::instance_memory) immediately after declaring it.
When SingletonOf<ObjectType> is being instantiated, ObjectType is incomplete. That's why you can't get the size of it.
However, the member function bodies of SingletonOf work as if they are placed just after the type. And those functions get instantiated at a point when ObjectType is complete. This is why ObjectType is complete and visible to member functions of SingletonOf<ObjectType>.
Your inner struct InstanceMemory is itself a template. And you instantiate it within a member function of the outer template. Since that member function sees ObjectType as complete, so too does InstanceMemory<ObjectType>.
All you have to do is make sure to instantiate InstanceMemory<ObjectType> at a point where ObjectType is complete.
I am a beginner in STL. I'm trying to code a toystl to learn STL. When I code about iterator, I'm puzzled if I should code a simple auto_ptr first and inherint from it.
I wrote a base class called iterator. And now it works like this,
struct iterator{};
template <class T>
struct vector_itorater: public toystl::iterator<toystl::random_access_iterator_tag, T>{};
If i need another base class works like a "auto_ptr"? just like this
// firstly define a sort of auto_ptr as base class
struct auto_ptr{};
// secondly inherint from auto_ptr
template <class T>
struct vector_itorater: public auto_ptr{};
Does this work? Or does STL do it like this?
I think you mixed up runtime polymorphy and compile time polymorphy. When the compiler instantiates a template, it cares about its visible interface of the concrete object. It does not care if this object has a inheritance relationship with other classes, it will pass as long as the concrete object can be used within the concrete context.
template <class C>
void foo(const C& bar)
{
// at the time of writing we don't know anything of C,
// only that it has a callable baz member (either a
// member function or a member with a call operator).
// This works, since the compiler knows the exact type
// during template instantiation, but we don't have to
// care in advance.
bar.baz();
}
struct X
{
void baz() const;
};
void grml()
{
X x;
// The compiler fills in X as the template type
// parameter for us. So the compiler creates a
// void foo<X>(const X&) function for us.
foo(x);
}
In this example when the compiler sees the template, it has no clue how this template will be called later. Only once the template gets instantiated (used), the compiler then will check if the passed type is suitable for this template.
Here it is not needed to have a common base class to derive every possible implementation from. The STL uses templates in order to avoid to use such base classes, since they give you a burden on your design later, and if you have virtual members in the base to override, you can get a serious performance penalty.
How do lines (2) and (3) even compile in the following C++ class, given that this is a pointer, so should need -> notation to access fields (as seen in line (1))? (Source)
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
template <typename T>
class sptr_wrapper
{
private:
boost::shared_ptr<T> sptr;
public:
template <typename ...ARGS>
explicit sptr_wrapper(ARGS... a)
{
this->sptr = boost::make_shared<T>(a...);
}
explicit sptr_wrapper(boost::shared_ptr<T> sptr)
{
this->sptr = sptr; // (1)
}
virtual ~sptr_wrapper() noexcept = default;
void set_from_sptr(boost::shared_ptr<T> sptr)
{
this.sptr = sptr; // (2)
}
boost::shared_ptr<T> get_sptr() const
{
return sptr; // (3)
}
};
The line (2) is invalid. As you said, this is a pointer, we need to use -> instead of .
As the member of class template, sptr_wrapper::set_from_sptr is not required to be instantiated, until it's used. So you can add some code trying to call it, then you might get compile-errors as you expect.
This applies to the members of the class template: unless the member is used in the program, it is not instantiated, and does not require a definition.
The line (3) is valid; sptr refers to the member sptr, which has the same effect as this->sptr.
When a non-static class member is used in any of the contexts where the this keyword is allowed (non-static member function bodies, member initializer lists, default member initializers), the implicit this-> is automatically added before the name, resulting in a member access expression (which, if the member is a virtual member function, results in a virtual function call).
Would you believe that the reason this compiles is because nothing really gets compiled here?
The shown code defines a template.
A template does not become "real" until it instantiates a class. Only at that time the compiler gets a closer look at the template, and attempts to figure WTF it's doing.
Sure, when defining a template the compiler makes a half-hearted attempt to parse the template, but only barely enough to satisfy itself that the template consists of some plausibly-looking C++ code.
If you add some additional lines to the shown code you'll get the compilation errors you were yearning for:
class X {};
void foo()
{
sptr_wrapper<X> x;
boost::shared_ptr<X> y;
x.set_from_sptr(y);
}
And this produces the compilation errors you were looking for:
t.C:27:14: error: request for member ‘sptr’ in ‘(sptr_wrapper<X>*)this’, which is of pointer type ‘sptr_wrapper<X>*’ (maybe you meant to use ‘->’ ?)
27 | this.sptr = sptr; // (2)
Note that merely instantiating
sptr_wrapper<X> x;
isn't enough. You have to go full throttle and invoke the method in question, before it becomes "real" in the eyes of a C++ compiler, and it chokes on it.
It's true that I can quite think of any circumstance where "this.foo" might be valid C++ code, but I'm sure that somewhere in the 2000 pages that make up the current C++ standard, the exact details of what's going on gets spelled out in a very pedantic way.
And you might consider dropping a note to your compiler's bug tracker, a feature request to have your compiler issue a friendly warning, in advance, when it sees something like this.
I have a class X which has this method:
void setRxHandler(void (*h)(int));
And I want to pass to it a member function that exists in instances of class Y.
void comm_rxHandler(int status);
I tried the following:
x.setRxHandler(comm_rxHandler)
But it get the following compile error (I'm using Qt):
error: no matching function for call to
‘X::setRxHandler(< unresolved overloaded function type>)’
So, how can I do that?
I noticed if I declare comm_rxHandler (class Y) as static, I have no errors. But I want comm_rxHandler as a non-static method. Also I want setRxHandler method (class X) to be generic and not class-specific. So I can't declare that method as:
setRxHandler(void (Y::*h)(int))
How to do that? Can you help me on this?
Thanks!
C++ doesn't support bound methods. To invoke a member function through a function pointer, you need to have two things: an instance of the class and the function pointer.
So setRxHandler(void (Y::*h)(int)) is almost correct. You need to declare it as:
void setRxHandler(Y*, void (Y::*h)(int));
To invoke setRxHandler(), you need to pass it arguments as follows:
Y y;
setRxHandler(&y, &Y::comm_rxHandler);
In the setRxHandler() method, you can invoke the function pointer using this syntax:
void setRxHandler ( Y* y, void (Y::*h)(int) )
{
// ...
(y->*h)(0);
// ...
}
To make generic, you need to abstract the Y parameter away, but this is difficult to get right. Check out Boost.Function for an existing implementation that supports this use case, and many more.
Change your callback to this:
void setRxHandler(std::function(<void(int)>);
Then you can use binders:
setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );
(std::function and std::bind are part of the upcomming next version of the C++ standard. It's quite likely your compiler already comes with them. If not, they might live in namespace std::tr1. If all else fails, you will find them at boost - which is where they were invented - as boost::function and boost::bind.)
You can, however, also pass non-member or static functions to setRxHandler, as well as function objects (which is the result of std::bind).
If your compiler already supports lambda functions (also part of the next standard, but already supported by, e.g., recent versions of GCC and VC), you can also use one of those:
setRxHandler( [](){obj.comm_rxHandler();} );
As it is now, the setRxHandler prototype takes a pointer to a function that doesn't return anything and takes an int. As you have noticed, this won't work with member functions because they can't be called like a normal function (you have to handle the this pointer as well, which means having an instance of that class to call the method on).
To make it both work with member functions and non-specific (generic), you have to either make a base class and have all classes you want to use setRxHandler with derive from that class:
class Base { ... };
class Derived : public Base { ... };
// then for the prototype
void setRxHandler(void (Base::*h)(int)) { ... }
// and you can use setRxHandler for all types that derive from Base, which gives you more control than the second option, which is:
or use templates:
template<typename T>
void setRxHandler(void (T::*h)(int)) { ... }
With the template option, you really have no control over what class will be used with setRxHandler (excluding RTTI), which can be exactly what you want.
You can either make a base class for Y and use that (to avoid being "class specific"), or use templates:
template <class T>
setRxHandler(void (T::*h)(int));
But then this may raise questions of how to use the member function (you tell us if it does).
As others have already mentioned, C++ does not provide this functionality.
Another option you could use is libsigc++ which is widely used in gtkmm, see this example in their tutorial for instance on how to pass pointers to member-functions. Your example could look something like:
// sigc::slot<void, int> is a 'slot' to hold a function with return type void
// and 1 int argument.
void setRxHandler(sigc::slot<void, int> slot);
void comm_rxHandler(int status);
//sigc::mem_fun() can convert a member function to a function slot.
x.setRxHandler(sigc::mem_fun(*this, &X::comm_rxHandler));
I have a templated class that performs an action on the class that is given as template argument. For some of my classes I want to 'group' the functionality in one class, to make it easier for the caller. In fact the code looks something like this (names were changed):
template<typename T>
class DoSomeProcessing
{
public:
process(T &t);
};
class ProcessingFrontEnd : public DoSomeProcessing<CustomerOrder>, public DoSomeProcessing<ProductionOrder>
{
};
The problem is that when I call ProcessingFrontEnd::process with a CustomerOrder as argument, that the compiler complains about it.
I tried to reproduce the problem in a smaller test application. This is the code:
#include <vector>
class X : public std::vector<char>
, public std::vector<void *>
{
};
int main(void)
{
X x;
x.push_back('c');
return 0;
}
And indeed, if this is compiled, Microsoft's VS2010 compiler gives this error:
test.cpp
test.cpp(11) : error C2385: ambiguous access of 'push_back'
could be the 'push_back' in base 'std::vector<char,std::allocator<char> >'
or could be the 'push_back' in base 'std::vector<void *,std::allocator<void *> >'
test.cpp(11) : error C3861: 'push_back': identifier not found
I tested this test application with different types (char+void*, double+void*) and different arguments in the call ('c', 3.14), but the error message is always the same.
I tested this with VS2005 and VS2010 but I always get the same error.
Why can't the compiler determine the correct function to call? What makes this confusing for the compiler? Or is it just a bug in the Microsoft compiler?
EDIT:
If I explicitly add 2 push_back methods to my class, like this:
class X : public std::vector<char>
, public std::vector<void *>
{
public:
void push_back(char c) {}
void push_back(void *p) {}
};
The compiler doesn't complain anymore. So with these methods he can clearly distinguish between a character and a void-pointer. Why can't he do this if the two push_back methods are inherited from the parent?
This is by design. The compiler is not trying to resolve overloaded
functions because these are not overloaded
functions. The standard is really clear on that
(see 10.2.2). If the same name is found in two
different bases, it's an ambiguity, even if they
could be resolved correctly with the call (i.e. in
your case). Same-named functions in different classes will typically have quite different purposes and hence the selection between them should not be made on the basis of
their arguments. There are many good reasons not to
allow that, but here's one.
Imagine your class C derives from A and B and
these two base classes come from two different
libraries. If the author of B adds a new function
to the class, it may break the user's code by
redirecting a call from A::foo() to B::foo() if
the latter is a better match.
If you want the two functions to be treated in the same way that they would
be if part of a single class, then the best way to do it is with using
declarations in the derived class. Just add
using std::vector<char>::push_back;
using std::vector<void *>::push_back;
to the declaration of class X.
I believe you are running afoul of the C++ overloading rules which prohibit overloading across classes. You'd get the same results if your template classes were two separate classes, each with its own process(CustomerOrder) and process(ProductionOrder) member.
The workaround is explicit using statements inside your derived class, pulling in each overload from each of the template base classes.
How is the compiler supposed to know which process you want to call? There's two options. Do you want both, one, or the other?
You need to override process in the derived class.