Can std::find function use for our own classes? - c++

I have set of classes. Each class is inherited from another class. The relationship is as follows. (I am just posting how one class inherited from another class, just to get idea for all of you)
class LineNumberList : public MyVector <LineNumber > //top class
class MyVector : public std::vector <Type>
class LineNumber : public ElementNumber
class ElementNumber { //this is the base class
protected:
int number;
public:
ElementNumber(int p){number=p;}
// some more codes //
}
Now, I want to implement a function which can be used to find elements inside my topclass i.e. LineNumberList. I tried with standard find function, but it doesn’t work. Can anyone help me to implement similar find function for my case, it is highly appreciated.

"I tried with standard find function, but it doesn’t work." Works for me:
#include <vector>
#include <iostream>
#include <algorithm>
class ElementNumber {
protected:
int number;
public:
ElementNumber(int p) :number(p) {}
bool operator==(const ElementNumber&e) { return number == e.number; }
};
class LineNumber : public ElementNumber {
public:
LineNumber(int p) : ElementNumber(p) {}
};
template <class Type>
class MyVector : public std::vector<Type> {
};
class LineNumberList : public MyVector<LineNumber> {
};
// EDIT: add local implementation of std::find
template<class InputIterator, class T>
InputIterator myfind ( InputIterator first, InputIterator last, const T& value )
{
http://www.cplusplus.com/reference/algorithm/find/
for ( ;first!=last; first++) if ( *first==value ) break;
return first;
}
int main() {
LineNumberList ll;
LineNumber l(7);
ll.push_back(l);
std::cout << std::boolalpha << !(std::find(ll.begin(), ll.end(), l) == ll.end()) << "\n";
std::cout << std::boolalpha << !(::myfind(ll.begin(), ll.end(), l) == ll.end()) << "\n";
}

Related

CRTP vs. vector of base class

I have an issue similar to this C++ vector of CRTP shared pointers but my problem formulation adds the fact that the return type of a function i want to use for all inheriting classes is templated.
In detail lets assume this :
template <class Derived>
class Base {
Derived Value() const {
return static_cast<Derived>(this->Value());
};
};
class ChildDouble : public Base<ChildDouble> {
public:
ChildDouble(double r) : _value(r){};
double Value() const {
return _value;
};
private:
double _value;
};
class ChildString : public Base<ChildDouble> {
public:
ChildString(string s) : _value(s){};
string Value() const {
return _value;
};
private:
string _value;
};
Goal would be to use it somewhat similar as in the following main
void main() {
std::vector<Base*> vec;
vec.push_back(new ChildDouble(3.0));
vec.push_back(new ChildString("Thomas"));
unsigned counter = 0;
for (const auto& e : vec) {
std::cout << "Entry " << counter << " : " << e->Value()
<< std::endl;
counter++;
}
}
The compiler is obviously not happy with this because Base requires a template argument.
Any Ideas how this could be solved? AM I using CRTP here although i should not be using it?
Virtual methods (which is what you'd normally need to get the above working without CRTP) won't work here because the interface is different for Value() in each derived type. Virtual inheritance depends on the signature being the same for everyone, except in a few special cases like with covariant return types. It also won't work because virtual methods can't be templated.
But, you can use std::variant to dynamically dispatch your incompatible interfaces, because it is based on templates. First, define a convenient alias for your variant:
using Child = std::variant<ChildDouble, ChildString>;
And then to use, dispatch with std::visit and a generic lambda:
std::vector<Child> vec;
vec.push_back(ChildDouble(3.0));
vec.push_back(ChildString("Thomas"));
unsigned counter = 0;
for (const auto& e : vec) {
std::visit([&counter](auto&& v) {
std::cout << "Entry " << counter << " : " << v.Value()
<< std::endl;
}, e);
counter++;
}
Demo: https://godbolt.org/z/bENWYW
It doesn't work because the compiler doesn't know which type you want to put in the vector and you need to specified it. If you try vector<Base<double>*>vec; it will works but you can't use the vector with other types like Base, because, it is other type.
The solution is to use std::variant or std::any in place of template.
Now you have an object variant/any the declare value in base will make your life easier.
Also I suggest you:
not to use variables starting with underline '_' because this syntax is used by many internal function of compiler.
not to use raw pointer. use smart_ptr like share_ptr then you don't need to worry to destroy it with delete.
Below the code with the changes:
#include <memory>
#include <vector>
#include <string>
#include <variant>
#include <iostream>
using namespace std;
struct Base {
Base(variant<double, string> val) : value(val) {}
void Print() { //just to ilustrate how it works. Better use ostream
if (holds_alternative<double>(this->value))
cout << get<double>(this->value);
else if (holds_alternative<string>(this->value))
cout << get<string>(this->value);
}
protected:
variant<double, string> value;
variant<double, string> BaseValue() const { return this->value; };
};
struct ChildDouble : public Base {
ChildDouble(double r) : Base(r) {};
double Value() const { return get<double>(this->BaseValue()); }
};
struct ChildString : public Base {
ChildString(string s) : Base(s) {};
string Value() const { return get<string>(this->BaseValue()); };
};
int main() { //must return int not void
vector<shared_ptr<Base>>vec;
vec.emplace_back(new ChildDouble(3.0));
vec.emplace_back(new ChildString("Thomas"));
unsigned counter = 0;
for (const auto& e : vec) {
cout << "Entry " << counter << " : "; e->Print(); cout << endl;
++counter;
}
}

how to add member-variable for a specialized version of a template class?

I have a template class, and at least 95% codes of it is same for all types of the template-parameter, unless a member-variable and a function should be added for one specialization.
The sample I want to get is following:
template <typename T>
class AClass {
private:
T payLoad;
public:
AClass( const T& crp_payload ) : payLoad( crp_payload ) {};
void showMe() {
cout << "Common showMe:" << payLoad << endl;
};
/*
* A lot of functions same for all specializations go here.
* I absolutely don't want to implement respectively them for
* every specializations!
*/
// specializing for int ----------------------------
// dedicated function
template <int>
void showPayload() {
cout << "AClass<int>::showPayload:" << payLoad << endl;
};
// dedicated variable, but following code can not be compiled!
template <int>
int otherPayload;
};
int main() {
AClass<int> iac( 123 );
iac.showMe();
iac.showPayload();//can not pass the compiling!
AClass<float> fac(456);
fac.showMe();
return 0;
};
My questions:
How to add merely "otherPayload" variable without re-coding entire
AClass<int>?
How to call showPayload() sinc I get a error msg when I
do it in main() as above.
Is there no way only by specializing to "revise/supplement" some
members to a class without totally re-implement it?
One possible way would be the good old inheritance:
template<class T> struct Extra {};
template<> struct Extra<int> {
int extraPayload;
void showPayload();
};
template<class T> class Class: public Extra<T> {
void showMe();
};
template<> void Class<int>::showMe() { showPayload(); }
All the specialization-specific parts are extracted in a separate class, and common methods are specialized as needed.
I think you can simply do normal specialization of the template-class:
#include <iostream>
#include <iomanip>
template <typename T>
class BaseClass
{
protected:
T payLoad;
public:
BaseClass(const T& crp_payload)
: payLoad( crp_payload )
{ }
void showMe() {
std::cout << "Common showMe:" << payLoad << std::endl;
}
/*
* A lot of functions same for all specializations go here.
* I absolutely don't want to implement respectively them for
* every specializations!
*/
};
template <typename T>
class AClass
: public BaseClass<T>
{
public:
AClass( const T& crp_payload )
: BaseClass<T>(crp_payload)
{ }
};
// specializing for int ----------------------------
template<>
class AClass<int>
: public BaseClass<int>
{
public:
AClass( int crp_payload )
: BaseClass(crp_payload)
{ }
// dedicated function
void showPayload() {
std::cout << "AClass<int>::showPayload:" << payLoad << std::endl;
}
private:
int otherPayload;
};
int main() {
AClass<int> iac( 123 );
iac.showMe();
iac.showPayload();//can not pass the compiling!
AClass<float> fac(456);
fac.showMe();
return 0;
}

Get derived class with base class function

I need to do some equality checks with different types on a class hierarchy. In pseudo code:
#include <string>
#include <memory>
#include <iostream>
using namespace std;
class ComplexType {};
class Property {};
class IntegerProperty : public Property {
public:
int inner;
};
class StringProperty : public Property {
public:
string inner;
};
class ComplexTypeProperty : public Property {
ComplexType inner;
};
int main() {
shared_ptr<Property> p1 = getSomewhere(); //this is in fact a pointer on IntegerProperty
shared_ptr<Property> p2 = getSomewhere(); // this is in fact a pointer on StringProperty
shared_ptr<Property> p3 = getSomewhere(); // this is in fact a pointer on CompleyTypeProperty
ComplexType c;
cout << ((*p1) == 2);
cout << ((*p2) == "foo");
cout << ((*p3) == c);
}
It it simple to provide a operator== for the derived classes, but I cannot cast before checking, because the type of p1 and p2 is not clear at compile time.
Another way I know is to write the operator== function in the Property base class and throw some exceptions if the type is wrong, but I want, that the Property class can be subclassed later without changing the code for Property and it will work, too.
Templating Property is also not (directly) possible, because e.g. in my code a vector<shared_ptr<Property>> has to exist.
Is there some (generic) way to implement main() to get the equality checks, so that later subclassing of Property without changing the class itself is possible?
Have found some way of solving this. I'm not quite happy with the code. So if anyone has a better solution, please provide it.
#include <string>
#include <memory>
#include <iostream>
using namespace std;
class ComplexType {
public:
bool operator==(const ComplexType& i) {
return true;
}
};
inline ostream& operator<<(ostream& os, const ComplexType& c) {
os << "ComplexType";
return os;
}
class Property {
public:
virtual ~Property() {}
};
template <class T>
class LayerProperty : public Property {
private:
T inner;
public:
LayerProperty(T t) : inner(t) {}
bool operator==(const T i) {
return inner == i;
}
};
int main() {
shared_ptr<Property> p1 = make_shared<LayerProperty<int>>(LayerProperty<int>(5));
shared_ptr<Property> p2 = make_shared<LayerProperty<string>>(LayerProperty<string>("foo"));
shared_ptr<Property> p3 = make_shared<LayerProperty<ComplexType>>(LayerProperty<ComplexType>(ComplexType()));
ComplexType c;
cout << ((*dynamic_pointer_cast<LayerProperty<decltype(2)>>(p1)) == 2) << "\n";
// special case std::string
auto a = "foo";
auto s = "";
if (typeid(a) == typeid(s)) {
cout << ((*dynamic_pointer_cast<LayerProperty<decltype(string(a))>>(p2)) == a) << "\n";
}
cout << ((*dynamic_pointer_cast<LayerProperty<decltype(c)>>(p3)) == c) << "\n";
return 0;
}

Calling parametrised method on list items with different template parameters

I'm trying to store and manipulate a list of template class objects with different parameter types; the template class has two parametrised methods, one returning the parameter type and a void one accepting it as input.
More specifically, I have a template class defined as follows:
template<typename T>
class Test
{
public:
virtual T a() = 0;
virtual void b(T t) = 0;
};
And different specifications of it, such as:
class TestInt : public Test<int>
{
public:
int a() {
return 1;
}
void b(int t) {
std::cout << t << std::endl;
}
};
class TestString : public Test<std::string>
{
public:
std::string a() {
return "test";
}
void b(std::string t) {
std::cout << t << std::endl;
}
};
I'd like to be able to store in one single list different objects of both TestInt and TestString type and loop through it calling one method as input for the other, as in:
for (auto it = list.begin(); it != list.end(); ++it)
(*it)->b((*it)->a());
I've looked into boost::any but I'm unable to cast the iterator to the specific class, because I don't know the specific parameter type of each stored object. Maybe this cannot be done in a statically typed language as C++, but I was wondering whether there could be a way around it.
Just for the sake of completeness, I'll add that my overall aim is to develop a "parametrised observer", namely being able to define an observer (as with the Observer Pattern) with different parameters: the Test class is the observer class, while the list of different types of observers that I'm trying to properly define is stored within the subject class, which notifies them all through the two methods a() and b().
The virtuals have actually no meaning here, since for each T the signatures are distinct.
So it seems you have Yet Another version of the eternal "how can we emulate virtual functions templates" or "how to create an interface without virtual functions":
Generating an interface without virtual functions?
How to achieve "virtual template function" in C++
The first one basically contains an idea that you could employ here.
Here's an idea of what I'd do:
Live On Coliru
#include <algorithm>
#include <iostream>
namespace mytypes {
template <typename T>
struct Test {
T a() const;
void b(T t) { std::cout << t << std::endl; }
};
template <> int Test<int>::a() const { return 1; }
template <> std::string Test<std::string>::a() const { return "test"; }
using TestInt = Test<int>;
using TestString = Test<std::string>;
}
#include <boost/variant.hpp>
namespace mytypes {
using Value = boost::variant<int, std::string>;
namespace detail {
struct a_f : boost::static_visitor<Value> {
template <typename T>
Value operator()(Test<T> const& o) const { return o.a(); }
};
struct b_f : boost::static_visitor<> {
template <typename T>
void operator()(Test<T>& o, T const& v) const { o.b(v); }
template <typename T, typename V>
void operator()(Test<T>&, V const&) const {
throw std::runtime_error(std::string("type mismatch: ") + __PRETTY_FUNCTION__);
}
};
}
template <typename O>
Value a(O const& obj) {
return boost::apply_visitor(detail::a_f{}, obj);
}
template <typename O, typename V>
void b(O& obj, V const& v) {
boost::apply_visitor(detail::b_f{}, obj, v);
}
}
#include <vector>
int main()
{
using namespace mytypes;
using AnyTest = boost::variant<TestInt, TestString>;
std::vector<AnyTest> list{TestInt(), TestString(), TestInt(), TestString()};
for (auto it = list.begin(); it != list.end(); ++it)
b(*it, a(*it));
}
This prints
1
test
1
test
Bonus Points
If you insist, you can wrap the AnyTest variant into a proper class and have a() and b(...) member functions on that:
Live On Coliru
int main()
{
using namespace mytypes;
std::vector<AnyTest> list{AnyTest(TestInt()), AnyTest(TestString()), AnyTest(TestInt()), AnyTest(TestString())};
for (auto it = list.begin(); it != list.end(); ++it)
it->b(it->a());
}
Expanding on my comment above, the simplest what I can currently think of to achieve what you are trying to do - at least as I understood it from your example code - is the following:
/* Interface for your container, better not forget the destructor! */
struct Test {
virtual void operate(void) = 0;
virtual ~Test() {}
};
/* Implementation hiding actual type */
template<typename T>
struct TestImpl : public T, public Test {
void operate(void) {
T::b(T::a());
}
};
/* Actual code as template policies */
struct IntTest {
int a(void) {
return 42;
}
void b(int value) {
std::cout << value << std::endl;
}
};
struct StringTest {
std::string a(void) {
return "Life? Don't talk to me about life.";
}
void b(std::string value) {
std::cout << value << std::endl;
}
};
You would then need to create a container for objects of class Test and fill it with objects of the respective TestImpl<IntTest>, TestImpl<StringTest>, and so on. To avoid object slicing you need reference or pointer semantics, that is std::vector<std::unique_ptr<Test> > for example.
for (auto it = list.begin(); it != list.end(); ++it) {
(*it)->operate();
}

Polymorphism in template parameter [duplicate]

I have this structure of classes.
class Interface {
// ...
};
class Foo : public Interface {
// ...
};
template <class T>
class Container {
// ...
};
And I have this constructor of some other class Bar.
Bar(const Container<Interface> & bar){
// ...
}
When I call the constructor this way I get a "no matching function" error.
Container<Foo> container ();
Bar * temp = new Bar(container);
What is wrong? Are templates not polymorphic?
I think the exact terminology for what you need is "template covariance", meaning that if B inherits from A, then somehow T<B> inherits from T<A>. This is not the case in C++, nor it is with Java and C# generics*.
There is a good reason to avoid template covariance: this will simply remove all type safety in the template class. Let me explain with the following example:
//Assume the following class hierarchy
class Fruit {...};
class Apple : public Fruit {...};
class Orange : public Fruit {...};
//Now I will use these types to instantiate a class template, namely std::vector
int main()
{
std::vector<Apple> apple_vec;
apple_vec.push_back(Apple()); //no problem here
//If templates were covariant, the following would be legal
std::vector<Fruit> & fruit_vec = apple_vec;
//push_back would expect a Fruit, so I could pass it an Orange
fruit_vec.push_back(Orange());
//Oh no! I just added an orange in my apple basket!
}
Consequently, you should consider T<A> and T<B> as completely unrelated types, regardless of the relation between A and B.
So how could you solve the issue you're facing? In Java and C#, you could use respectively bounded wildcards and constraints:
//Java code
Bar(Container<? extends Interface) {...}
//C# code
Bar<T>(Container<T> container) where T : Interface {...}
The next C++ Standard (known as C++1x (formerly C++0x)) initially contained an even more powerful mechanism named Concepts, that would have let developers enforce syntaxic and/or semantic requirements on template parameters, but was unfortunately postponed to a later date. However, Boost has a Concept Check library that may interest you.
Nevertheless, concepts might be a little overkill for the problem you encounter, an using a simple static assert as proposed by #gf is probably the best solution.
* Update: Since .Net Framework 4, it is possible to mark generic parameters has being covariant or contravariant.
There are two problems here: default constructions have the form MyClass c;; with parentheses it looks like a function declaration to the compiler.
The other problem is that Container<Interface> is simply a different type then Container<Foo> - you could do the following instead to actually get polymorphism:
Bar::Bar(const Container<Interface*>&) {}
Container<Interface*> container;
container.push_back(new Foo);
Bar* temp = new Bar(container);
Or of course you could make Bar or its constructor a template as Kornel has shown.
If you actually want some type-safe compile-time polymorphism, you could use Boost.TypeTraits is_base_of or some equivalent:
template<class T>
Bar::Bar(const Container<T>& c) {
BOOST_STATIC_ASSERT((boost::is_base_of<Interface, T>::value));
// ... will give a compile time error if T doesn't
// inherit from Interface
}
No. Imagine that the container parameter is "hardcoded" into the class it defines (and that is actually how it works). Hence the container type is Container_Foo, that is not compatible with Container_Interface.
What you might try however is this:
template<class T>
Bar(const Container<T> & bar){
...
}
Yet you loose direct type checking that way.
Actually the STL way (probably more effective and generic) would be to do
template<class InputIterator>
Bar(InputIterator begin, InputIterator end){
...
}
... but I assume you don't have iterators implemented in the container.
It is possible to create an inheritance tree for containers, reflecting the inheritance tree of the data. If you have the following data:
class Interface {
public:
virtual ~Interface()
{}
virtual void print() = 0;
};
class Number : public Interface {
public:
Number(int value) : x( value )
{}
int get() const
{ return x; }
void print()
{ std::printf( "%d\n", get() ); };
private:
int x;
};
class String : public Interface {
public:
String(const std::string & value) : x( value )
{}
const std::string &get() const
{ return x; }
void print()
{ std::printf( "%s\n", get().c_str() ); }
private:
std::string x;
};
You could also have the following containers:
class GenericContainer {
public:
GenericContainer()
{}
~GenericContainer()
{ v.clear(); }
virtual void add(Interface &obj)
{ v.push_back( &obj ); }
Interface &get(unsigned int i)
{ return *v[ i ]; }
unsigned int size() const
{ return v.size(); }
private:
std::vector<Interface *> v;
};
class NumericContainer : public GenericContainer {
public:
virtual void add(Number &obj)
{ GenericContainer::add( obj ); }
Number &get(unsigned int i)
{ return (Number &) GenericContainer::get( i ); }
};
class TextContainer : public GenericContainer {
public:
virtual void add(String &obj)
{ GenericContainer::add( obj ); }
String &get(unsigned int i)
{ return (String &) GenericContainer::get( i ); }
};
This is not the best performing code; it is just to give an idea. The only problem with this approach is that every time you add a new Data class, you have to also create a new Container. Apart from that, you have polymorphism "working again". You can be specific or general:
void print(GenericContainer & x)
{
for(unsigned int i = 0; i < x.size(); ++i) {
x.get( i ).print();
}
}
void printNumbers(NumericContainer & x)
{
for(unsigned int i = 0; i < x.size(); ++i) {
printf( "Number: " );
x.get( i ).print();
}
}
int main()
{
TextContainer strContainer;
NumericContainer numContainer;
Number n( 345 );
String s( "Hello" );
numContainer.add( n );
strContainer.add( s );
print( strContainer );
print( numContainer );
printNumbers( numContainer );
}
I propose the following workaround, which employs a template function. Although the example use Qt's QList, nothing prevents the solution from being straightforwardly transposed to any other container.
template <class D, class B> // D (Derived) inherits from B (Base)
QList<B> toBaseList(QList<D> derivedList)
{
QList<B> baseList;
for (int i = 0; i < derivedList.size(); ++i) {
baseList.append(derivedList[i]);
}
return baseList;
}
Pros:
general
type-safe
fairly efficient if the items are pointers or some other cheaply copy-constructible elements (such as implicitly shared Qt classes)
Cons:
requires the creation of a new container, as opposed to enabling the reuse of the original one
implies some memory and processor overhead both to create and to populate the new container, which depend heavily on the cost of the copy-constructor
#include <iostream>
#include <sstream>
#include <map>
#include <vector>
struct Base { int b = 111; };
struct Derived: public Base { };
struct ObjectStringizer {
template <typename T>
static std::string to_string(const T& t) {
return helper<T>()(t);
}
template <typename T, typename = void>
struct helper {
std::string operator()(const T& t) {
std::ostringstream oss;
oss << t;
return oss.str();
}
};
template <typename T>
struct helper<T, typename std::enable_if<std::is_base_of<Base, T>::value>::type> {
std::string operator()(const T& base) {
return to_string(base.b);
}
};
template <typename T>
struct helper<std::vector<T>> {
std::string operator()(const std::vector<T>& v) {
std::ostringstream oss;
for (size_t i = 0, sz = v.size(); i < sz; ++i) {
oss << (i ? "," : "") << to_string(v[i]);
}
return "[" + oss.str() + "]";
}
};
template <typename Key, typename Value>
struct helper<std::map<Key, Value>> {
std::string operator()(const std::map<Key, Value>& m) {
std::ostringstream oss;
for (auto iter = m.begin(), iter_end = m.end(); iter_end != iter; ++iter) {
oss << (m.begin() != iter ? "," : "") << to_string(iter->first) << ":" << to_string(iter->second);
}
return "{" + oss.str() + "}";
}
};
};
int main(int argc, char* argv[]) {
std::cout << ObjectStringizer::to_string("hello ") << ObjectStringizer::to_string(std::string("world")) << std::endl;
std::cout << ObjectStringizer::to_string(Derived()) << std::endl;
std::cout << ObjectStringizer::to_string(std::vector<int>{3, 5, 7, 9}) << std::endl;
std::cout << ObjectStringizer::to_string(std::map<int, std::string>{{1, "one"}, {2, "two"}}) << std::endl;
return 0;
}
container is a container of Foo objects not a container of Interface objects
And it cannot be polymorphic either, pointers to things can be ,but not the objects themselvs. How big would the slots in the container have to be for container if you could put anything derived from interface in it
you need
container<Interface*>
or better
container<shared_ptr<Interface> >