Is there any safe std::any_cast and dynamic_cast combination?
I'm trying to perform the following:
struct V
{
virtual void x( ) { std::cout << "V"; }
};
struct A: V
{
void x( ) override { std::cout << "A"; }
};
struct B: V
{
void x( ) override { std::cout << "B"; }
};
struct C: A, B
{
void x( ) override { std::cout << "C"; }
};
int main( )
{
// In my code, I cannot change the template argument
// to be a base class and construct it with a child
// class due to requirements of my implementation
auto c = std::make_any< C >( );
#if 0 // doesn't work
std::any_cast< B >( c ).x( );
std::any_cast< A >( c ).x( );
#else // works, but requires knowing the type is C
dynamic_cast< B && >( std::any_cast< C >( c ) ).x( );
dynamic_cast< A && >( std::any_cast< C >( c ) ).x( );
#endif
}
Related
I have two classes, I'll call them "foo" and "bar". "foo" has two public members: (a string for its name and a vector of type "bar").
class bar {
//not important
};
class foo {
public:
std::string fooName;
std::vector<bar> bars;
}
If I have an element of bars, how can I access and print its corresponding fooName? I'm thinking about something along these lines, but I don't know how to fill in the blank:
std::cout << bars[index].__________.fooName;
When I try googling an answer, I can only find people asking about accessing private members of other classes.
So I'm not totally sure if this is what you're after but if your foo object contains the collection of bar objects then you should know which foo objects name to print.
struct Bar
{ std::string name; };
struct Foo
{
Foo( std::string fooName )
: name{ std::move( fooName ) } { }
void AddBar( Bar bar )
{ bars.push_back( std::move( bar ) ); }
bool Contains( std::string_view barName ) const
{
return ( std::find_if( std::begin( bars ), std::end( bars ),
[ &barName ]( const Bar& bar ) {
return bar.name.compare( barName ) == 0;
}) != std::end( bars ) );
}
std::string name;
std::vector<Bar> bars;
};
int main( )
{
Foo foo{ "North America" };
foo.AddBar( { "New York" } );
foo.AddBar( { "LA" } );
foo.AddBar( { "Toronto" } );
foo.AddBar( { "Seattle" } );
foo.AddBar( { "BC" } );
foo.AddBar( { "Winnipeg" } );
// Check if a single foo instance contains the city.
if ( foo.Contains( "Toronto" ) )
std::cout << "City: Toronto Continent: " << foo.name << '\n';
Foo foo2{ "South America" };
foo2.AddBar( { "Lima" } );
foo2.AddBar( { "Santiago" } );
foo2.AddBar( { "Salvador" } );
foo2.AddBar( { "Fortaleza" } );
foo2.AddBar( { "Quito" } );
std::vector<Foo> foos{ std::move( foo ), std::move( foo2 ) };
// Check if any foo instance contains a specific city.
const std::string cityName{ "Toronto" };
auto it{ std::find_if( std::begin( foos ), std::end( foos ),
[ &cityName ]( const Foo& foo ) { return foo.Contains( cityName ); } ) };
if ( it != std::end( foos ) )
std::cout << "Continent: " << it->name << '\n';
}
I'm trying to associate compile time strings to enum values.
Here is my first attempt at the problem:
EnumValue will do the compile time assocation between a string and an enum
template<typename EnumType, int EnumIntValue, const char* EnumStrValue>
class EnumValue
{
public:
static const char* toString()
{
return EnumStrValue;
}
static const int toInt()
{
return EnumIntValue;
}
static EnumType get()
{
return static_cast<EnumType>(EnumIntValue);
}
};
EnumValueHolder will hold the actual values for both string and enum.
I dislike my current design as it still needs to hold a pointer to string. I would prefer a compile time association for this but fail to come up with a more elegant solution
template<typename EnumType>
class EnumValueHolder
{
public:
EnumValueHolder()
{}
EnumValueHolder(const EnumType& value, const char* str)
: value(value), str(str)
{}
bool operator==(const EnumValueHolder<EnumType>& rhs) { return value == rhs.value; }
bool operator==(const EnumType& rhs)const { return value == rhs; }
operator EnumType()const
{
return value;
}
const char* toString()const
{
return str;
}
const int toInt()const
{
return static_cast<int>(value);
}
private:
EnumType value;
char const* str;
};
Marcos to easily refer to enum types and enum value holder construction
#define ENUM_VALUE_TYPE(enumName, enumValue) \
EnumValue<enumName, (int)enumName::enumValue, str_##enumValue>
#define ENUM_VALUE_MAKE(enumName, enumValue) \
EnumValueHolder<enumName> { \
ENUM_VALUE_TYPE(enumName, enumValue)::get(), \
ENUM_VALUE_TYPE(enumName, enumValue)::toString() }
The following are my test cases and usage examples:
const char str_Apple[] = "Apple";
const char str_Orange[] = "Orange";
const char str_Pineapple[] = "Pineapple";
enum class EFruits
{
Apple,
Orange,
Pineapple
};
int main()
{
auto evApple = ENUM_VALUE_MAKE(EFruits, Apple);
std::cout << evApple.toString() << std::endl;
auto evOrange = ENUM_VALUE_MAKE(EFruits, Orange);
std::cout << evOrange.toString() << std::endl;
std::cout << "compare: " << (evApple == evOrange) << std::endl;
evApple = evOrange;
std::cout << evApple.toString() << std::endl;
auto myfruit = ENUM_VALUE_MAKE(EFruits, Pineapple);
std::cout << myfruit.toString() << std::endl;
switch (myfruit)
{
case EFruits::Apple:
std::cout << "Im an apple!" << std::endl;
break;
case EFruits::Orange:
std::cout << "Im an Orange!" << std::endl;
break;
case EFruits::Pineapple:
std::cout << "Im a Pineapple!" << std::endl;
break;
default:break;
}
}
One of the objectives is to remove the global string:
const char str_Apple[] = "Apple";
const char str_Orange[] = "Orange";
const char str_Pineapple[] = "Pineapple";
The other is to create a macro that assoicates an enum with a string
//Some crazy define that makes pairs of enum values and strings as
//compile time constants
#define DEFINE_ENUM_STRING(enumValue)\
enumValue, #enumValue
//Ideally, the macro would be used like this. This should be usable in any
//scope (global, namespace, class)
//with any access specifier (private, protected, public)
enum class EFruits
{
DEFINE_ENUM_STRING(Apple),
DEFINE_ENUM_STRING(Orange),
DEFINE_ENUM_STRING(Pineapple)
};
So there are 2 main questions:
1) Will this current design actually guarantee compile time constants for associating the enum to the string?
2) How can I define a macro to stringify an enum value and declare the value in a enum class using 1 line?
Edit: This should work and compile with msvs2017 on win64 platform using c++ 11.
Thanks.
I think it should work with MSVC2017. It uses C++14 in the constexpr functions but you can split them to single return statement constexprs to be C++11 compatible (however MSVC2017 supports C++14).
EnumConverter stores the char*, the enum and a string hash value for each enum entry. For each enum you must specialize EnumConverter::StrEnumContainer. The enum-string pairs could be generated with a similar macro you specified.
#include <tuple>
#include <array>
#include <stdexcept>
using namespace std;
enum ELogLevel {
Info,
Warn,
Debug,
Error,
Critical
};
static constexpr size_t constexprStringHash( char const* const str ) noexcept
{
return (
( *str != 0 ) ?
( static_cast< size_t >( *str ) + 33 * constexprStringHash( str + 1 ) ) :
5381
);
}
class EnumConverter final
{
public:
EnumConverter() = delete;
EnumConverter( const EnumConverter& ) = delete;
EnumConverter( EnumConverter&& ) = delete;
EnumConverter& operator =( const EnumConverter& ) = delete;
EnumConverter& operator =( EnumConverter&& ) = delete;
template< typename ENUM_T >
static constexpr const char* toStr( const ENUM_T value )
{
const auto& strEnumArray{ StrEnumContainer< ENUM_T >::StrEnumPairs };
const char* result{ nullptr };
for( size_t index{ 0 }; index < strEnumArray.size(); ++index ) {
if( std::get< 1 >( strEnumArray[ index ] ) == value ) {
result = std::get< 0 >( strEnumArray[ index ] );
break;
}
}
return ( ( result == nullptr ) ? throw std::logic_error{ "Enum toStrBase conversion failed" } : result );
}
template< typename ENUM_T >
static constexpr ENUM_T fromStr( const char* const str )
{
const auto& strEnumArray{ StrEnumContainer< ENUM_T >::StrEnumPairs };
const size_t hash{ constexprStringHash( str ) };
const ENUM_T* result{ nullptr };
for( size_t index{ 0 }; index < strEnumArray.size(); ++index ) {
if( std::get< 2 >( strEnumArray[ index ] ) == hash ) {
result = &( std::get< 1 >( strEnumArray[ index ] ) );
}
}
return ( ( result == nullptr ) ? throw std::logic_error{ "Enum toStrBase conversion failed" } : *result );
}
private:
template< typename ENUM_T, size_t LEN >
using ARRAY_T = std::array< std::tuple< const char* const, const ENUM_T, const size_t >, LEN >;
template< typename ENUM_T >
static constexpr std::tuple< const char* const, ENUM_T, size_t > getTuple( const char* const str, const ENUM_T type ) noexcept
{
return std::tuple< const char* const, ENUM_T, size_t >{ str, type, constexprStringHash( str ) };
}
template< typename ENUM_T >
struct StrEnumContainer
{
};
template< typename ENUM_T >
friend struct StrEnumContainer;
};
template<>
struct EnumConverter::StrEnumContainer< ELogLevel >
{
using ENUM_T = ELogLevel;
static constexpr EnumConverter::ARRAY_T< ENUM_T, 5 > StrEnumPairs{ {
{ getTuple( "Info", ENUM_T::Info ) },
{ getTuple( "Warn", ENUM_T::Warn ) },
{ getTuple( "Debug", ENUM_T::Debug ) },
{ getTuple( "Error", ENUM_T::Error ) },
{ getTuple( "Critical", ENUM_T::Critical ) },
} };
};
int main()
{
//static_assert( EnumConverter::fromStr< ELogLevel >( "Info" ) == EnumConverter::fromStr< ELogLevel >( EnumConverter::toStr( Error ) ), "Error" ); // Error
static_assert(
EnumConverter::toStr( Warn )[ 0 ] == 'W' &&
EnumConverter::toStr( Warn )[ 1 ] == 'a' &&
EnumConverter::toStr( Warn )[ 2 ] == 'r' &&
EnumConverter::toStr( Warn )[ 3 ] == 'n',
"Error"
);
static_assert( EnumConverter::fromStr< ELogLevel >( "Info" ) == EnumConverter::fromStr< ELogLevel >( EnumConverter::toStr( Info ) ), "Error" );
}
I thought this is already very simple and not doing much (Took it from one of the stack overflow question answer code), but running a loop of 100K times shows it's slower than boost::shared_ptr. Baffled, where is the slowness come from?
template <class T>
class sp_shared_ptr
{
public:
inline sp_shared_ptr() noexcept: p_(), count_() {}
inline explicit sp_shared_ptr( T* p ) noexcept: p_( p ), count_( new int(1) ) {}
inline sp_shared_ptr( const sp_shared_ptr& sp ) noexcept: p_( sp.p_ ), count_( sp.count_ )
{
if( count_ ) ++(*count_);
}
// EDIT: add in later based on comments
sp_shared_ptr( sp_shared_ptr && r ) noexcept : p_( r.p_ ), count_()
{
int *tmp = r.count_;
r.count_ = count_;
count_ = tmp;
r.p_ = 0;
}
sp_shared_ptr& operator=( const sp_shared_ptr& sp ) noexcept
{
if( this != &sp )
{
clear();
p_ = sp.p_;
count_ = sp.count_;
if( count_ ) ++*count_;
}
return *this;
}
~sp_shared_ptr() noexcept
{
clear();
}
private:
inline void clear() noexcept
{
if( count_ )
{
--*count_;
if( *count_ == 0 ) {
delete p_; p_=0;
delete count_; count_=0;
}
}
}
T* get() const { return count_ ? p_ : 0; }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* p_;
int* count_;
};
The output of the following program is:
10229594
14577150
14030158
EDIT: Based on #BoPersson's comment, edit in the move constructor. Now, result is getting closer:
10201099
14121221
14040181
I wonder why it is faster, or quite a bit faster (No atomic counter didn't do any good in my test?)
Calling program:
#include <iostream>
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr.hpp>
#include <time.h>
#include "sp_shared_ptr.h"
struct A
{
int a1;
double a2;
std::string a3;
};
long long duration( const timespec& t0, const timespec& t1 )
{
return (t1.tv_sec*1000000000L + t1.tv_nsec) - (t0.tv_sec*1000000000L + t0.tv_nsec);
}
int main()
{
typedef std::vector<std::unique_ptr<A>> UPVector;
typedef std::vector<boost::shared_ptr<A>> SPVector;
typedef std::vector<sp_shared_ptr<A>> MySPVector;
UPVector v1;
SPVector v2;
MySPVector v3;
const int n=100000;
timespec t0, t1;
clock_gettime( CLOCK_REALTIME, &t0 );
clock_gettime( CLOCK_REALTIME, &t0 );
{
for( auto i=0; i < n; ++i )
v1.push_back( std::unique_ptr<A>( new A { i, i/100.0, "aaaaaaaaaa" } ) );
}
clock_gettime( CLOCK_REALTIME, &t1 );
std::cout << duration( t0, t1 ) << std::endl;
clock_gettime( CLOCK_REALTIME, &t0 );
{
for( auto i=0; i < n; ++i )
v3.push_back( sp_shared_ptr<A>( new A{ i, i/100.0, "aaaaaaaaaa" } ) );
}
clock_gettime( CLOCK_REALTIME, &t1 );
std::cout << duration( t0, t1 ) << std::endl;
clock_gettime( CLOCK_REALTIME, &t0 );
{
for( auto i=0; i < n; ++i )
v2.push_back( boost::shared_ptr<A>( new A{ i, i/100.0, "aaaaaaaaaa" } ) );
}
clock_gettime( CLOCK_REALTIME, &t1 );
std::cout << duration( t0, t1 ) << std::endl;
return 0;
}
I am trying to compare different classes of objects in C++.
Everything works well if I remove section3. But I'd like to know how to edit the comparative operators == and != to make it work without any errors?
The error that I get is "no match for 'operator==' (operand types are 'Fruit' and 'Plant') "
Here is my code :
#include <iostream>
#include <string>
class Plant
{
public:
Plant(std::string name) : type_(name)
{ }
bool operator==(const Plant &that) const
{ return type_ == that.type_; }
bool operator!=(const Plant &that) const
{ return !operator==(that); }
void print()
{ std::cout << type_ << std::endl; }
protected:
std::string type_;
};
class Fruit: public Plant
{
public:
Fruit(std::string name, std::string taste)
: Plant(name)
, taste_(taste)
{ }
bool operator==(const Fruit& that) const
{
return ( (taste_ == that.taste_) && (Plant::operator==(that)) );
}
bool operator!=(const Fruit& that) const
{
return !operator==(that);
}
void print()
{
Plant::print();
std::cout << taste_ << std::endl;
}
private:
std::string taste_;
};
int main()
{
Plant a("Maple");
a.print();
Plant b("Maple");
if (a == b)
{
std::cout << "a and b are equal" << std::endl;
}
else
{
std::cout << "a and b are not equal" << std::endl;
}
Fruit c("Apple","sweet");
c.print();
Fruit d("Apple","sweet");
if (c == d)
{
std::cout << "c and d are equal" << std::endl;
}
else
{
std::cout << "c and d are not equal" << std::endl;
}
if (a == c)
{
std::cout << "a and c are equal" << std::endl;
}
else
{
std::cout << "a and c are not equal" << std::endl;
}
/* Section 3 */
if (c == a)
{ std::cout <<"c and a are equal\n"<< std::endl; }
else
{ std::cout <<"c and a are not equal\n"<< std::endl; }
if (a != c)
{ std::cout <<"c and a are not equal\n"<< std::endl; }
else
{ std::cout <<"c and a are equal\n"<< std::endl; }
return 0;
}
Thanks ..
You can add non-member functions,
bool operator==(Fruit const& f, Plant const& p)
{
return false;
}
bool operator!=(Fruit const& f, Plant const& p)
{
return !(f == p);
}
This will work for one sub-type of Plant. This approach is not scalable. If you create more sub-types of Plant, you'll need to use a different approach.
You have to either implement comparitor operators to compare Fruit and Plant or downcast the Fruit to a plant in the comparison:
bool operator==(const Plant& plant, const Fruit& fruit) { /* test here */ }
bool operator==(const Fruit& fruit, const Plant& plant) { return (plant == fruit); }
Or if you have pointers:
Fruit* fruit = new Fruit("apple", "sour");
Plant* plant = new Plant("maple");
if(*plant == *static_cast<Plant*>(fruit)) {}
It's bit unclear what you're trying to achieve, but apparently it involves dynamic type checking where two objects compare equal if they dynamically are of some common base type X and are equal according to some criterion specified in that base type.
Finding the common type X is in general a thorny problem, because C++ supports multiple inheritance. But if one assumes, for simplicity, single inheritance, that is, the case where each class has at most one base class, then one can let one of the objects that are involved in a comparison, walk up the base class chain and use e.g. dynamic_cast to check if the other object is of this type, e.g. like this:
#include <string>
#include <utility> // std::move
using Byte_string = std::string;
class Base
{
private:
Byte_string s_;
protected:
virtual
auto equals( Base const& other ) const
-> bool
{ return s_ == other.s_; }
public:
friend
auto operator==( Base const& a, Base const& b )
-> bool
{ return a.equals( b ); }
explicit Base( Byte_string s )
: s_( move( s ) )
{}
};
class Derived
: public Base
{
private:
Byte_string t_;
protected:
auto equals( Base const& other ) const
-> bool override
{
if( auto p_other = dynamic_cast<Derived const*>( &other ) )
{
return Base::equals( other ) and t_ == p_other->t_;
}
return Base::equals( other );
}
public:
Derived( Byte_string s, Byte_string t )
: Base( move( s ) )
, t_( move( t ) )
{}
};
class Most_derived
: public Derived
{
private:
int u_;
protected:
auto equals( Base const& other ) const
-> bool override
{
if( auto p_other = dynamic_cast<Most_derived const*>( &other ) )
{
return Derived::equals( other ) and u_ == p_other->u_;
}
return Derived::equals( other );
}
Most_derived( Byte_string s, Byte_string t, int u )
: Derived( move( s ), move( t ) )
, u_( u )
{}
};
#include <iostream>
using namespace std;
auto main() -> int
{
Base a( "Maple" );
Base b( "Maple" );
cout << "a and b are " << (a == b? "" : "not ") << "equal.\n";
Derived c( "Apple", "sweet" );
Derived d( "Apple", "sweet" );
cout << "c and d are " << (c == d? "" : "not ") << "equal.\n";
cout << "a and c are " << (a == c? "" : "not ") << "equal.\n";
cout << "c and a are " << (c == a? "" : "not ") << "equal.\n";
Base& x = d;
cout << "x and c are " << (x == c? "" : "not ") << "equal.\n";
cout << "c and x are " << (c == x? "" : "not ") << "equal.\n";
}
I have a template class C. I want such a template copy constructor that it will resize the data array according to the size of the other class.
The following is a simple example. It works fine. However, notice that Constructor 2 and Constructor 3 are so similar, I am wondering whether it is possible to merge them as one?
Also, if I simple remove Constructor 3, then C<int> c3( c1 ) won't call Constructor 2, but will rather call a default copy constructor added by the compiler. This will result in the memory not being allocated properly.
template<typename T>
class C
{
public:
T* val;
int size;
public:
C( int s = 0 ) {
cout << "Constructor 1" << endl;
size = s;
val = ( size ) ? new T[size] : nullptr;
}
template<class T2>
C( const C<T2>& c2 ) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
C( const C<T>& c2 ) {
cout << "Constructor 3" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
~C() {
cout << "~C()" << endl;
delete[] val;
val = nullptr;
}
};
int main(void)
{
C<int> c1( 5 );
C<float> c2( c1 );
C<int> c3( c1 );
return 0;
}
Output of the above function:
Constructor 1
Constructor 2
Constructor 3
~C()
~C()
~C()
Replace
template<class T2>
C( const C<T2>& c2 ) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
C( const C<T>& c2 ) {
cout << "Constructor 3" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
by
template<class T2>
C( const C<T2>& c2, int dummy) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}
template<class T2>
C( const C<T2>& c2 ) : C(c2, 0) {}
C( const C<T>& c2 ) : C(c2, 0) {}
Update
You can just use:
C( int s = 0 ) {
cout << "Constructor 1" << endl;
size = s;
val = ( size ) ? new T[size] : nullptr;
}
template<class T2>
C( const C<T2>& c2 ) : C(c2.size) {}
C( const C<T>& c2 ) : C(c2.size) {}
and not need the second constructor.
One would like to implement this with a C++11 delegating constructor. However due to ambiguity in if template paramaters are to the class or to the constructor, this is not possible in a straightforward manner. As a workaround one can factor out the common code into a helper function.
something like:
template<class T2>
C( const C<T2>& c2 ) {
Copy<T2>(c2);
}
C( const C<T>& c2 ) {
Copy<T>(c2);
}
private:
template<class T2>
void Copy( const C<T2>& c2 ) {
cout << "Constructor 2" << endl;
size = c2.size;
val = ( size ) ? new T[size] : nullptr;
}