First of all I want a normal enumeration instead of a bit-based enumeration, because the amount of different enums will be beyond any integral type. I also want to take advantage of the type safety of C++11 enum class. To do so, the natural choice would be std::bitset, however I have no idea how to bind those two together.
A custom bitset would be needed? How to go around the implementation of such a class?
Since enum classes are wrappers for enums, you can cast them to underlying type. And using some private inheritance you can selectively import some functionalities from C++ stdlib classes without worrying about Liskov's principle. Composition resulted in clearer code. Using these functionalities, we can wrap std::bitset. Following code contains only subset of functionalites, but it can be expanded further.
There's a problem with max value - that you can't get maximum value of enum class (or am I wrong?). So I added EnumTraits. Now users are required to specialize EnumTraits with const value max equal to the max value of enum before class can be used.
#include <bitset>
#include <type_traits>
template<typename T>
struct EnumTraits;
template<typename T>
class EnumClassBitset
{
private:
std::bitset<static_cast<typename std::underlying_type<T>::type>(EnumTraits<T>::max)> c;
typename std::underlying_type<T>::type get_value(T v) const
{
return static_cast<typename std::underlying_type<T>::type>(v);
}
public:
EnumClassBitset() : c()
{
}
bool test(T pos) const
{
return c.test(get_value(pos));
}
EnumClassBitset& reset(T pos)
{
c.reset(get_value(pos));
return *this;
}
EnumClassBitset& flip(T pos)
{
c.flip(get_value(pos));
return *this;
}
};
enum class BitFlags
{
False,
True,
FileNotFound,
Write,
Read,
MaxVal
};
template<>
struct EnumTraits<BitFlags>
{
static const BitFlags max = BitFlags::MaxVal;
};
#include <iostream>
int main()
{
EnumClassBitset<BitFlags> f;
f.flip(BitFlags::True);
f.flip(BitFlags::FileNotFound);
//f.flip(2); //fails to compile
std::cout << "Is False? " << f.test(BitFlags::False) << "\n";
std::cout << "Is True? " << f.test(BitFlags::True) << "\n";
std::cout << "Is FileNotFound? " << f.test(BitFlags::FileNotFound) << "\n";
std::cout << "Is Write? " << f.test(BitFlags::Write) << "\n";
std::cout << "Is Read? " << f.test(BitFlags::Read) << "\n";
}
Since enums don't have much functionality unfortunately, and what is more, C++11 with enum classes don't improve the situation, some programmers use static map wrapped in a class. Definitely a good read.
Related
#include <iostream>
template<typename _OutType, typename _InType>
struct ConvertClass
{
_OutType operator()(_InType src)
{
return _OutType(src);
}
};
class OutClass
{
public:
OutClass(std::string str)
{
std::cout << "construct function works well!" << std::endl;
}
};
int main()
{
ConvertClass<OutClass, int>()(20); // this is wrong, because the OutClass only have one construct which takes the std::string type parameter.
// ConvertClass<OutClass, std::string>()(std::string("Hello!"));
/*
if (...) // So I wonder if there is any way that we can know whether the construct function is exists or not before we call the OutClass(int i) function
{
std::cout << "there is no such construct function of OutClass to take that parameter type" << std::endl;
return -1;
}
else
{
std::cout << "construct function works well!" << std::endl;
return 0;
}
*/
}
My Problem:
I know the main function is definitely wrong for the OutClass don't have the construct function OutClass(string str).
I wonder if there is a way only to change the Comment 1 section, the template class to make this file be compiled and linked successfully.
My English is not good, hoping you guys don't mind!
Thank you !
to my knowledge there is not runtime checking if given class is constructible using argument of given type
as said in my previous answer you can resort to Concepts and check the types at compiletime, but if clause does not work at compile time
To me it looks like the best solution would be indeed making a template class out of OutClass, then you have a single class with serves diverse purposes, dependent on you needs
one more edit to your code, I see that you pass the _OutType and _InType to your template.
In the setting where we have the following class template
template<class srcType>
class OutType:{
srcType src;
public:
OutType(srcType src) : src(src) {std::cout << "constructor works well!" << std::endl;}
}
then while invoking the class ConvertClass:
auto val = ConvertClass<OutClass<std::string>, std::string>()(std::string("Hello!"));
and also this will work:
auto val = ConvertClass<OutClass<int>, int>(20);
however, since operator() is not a static method you need first to construct object of class ConvertClass
In c++20 or even in c++17 you can in fact check if OutClass is constructible from int:
so your if clause should look like this
if(std::is_constructible<OutClass, int>::value) {
std::cout << "all is well" << std::endl;
}else{
std::cout << "you can't construct OutClass from int" << std::endl;
}
you can make the the following class template from the OutClass
template<class SrcType>
class OutClass {
SrcType src;
public:
OutClass(SrcType src) : src(src) {}
}
then in your code
return OutType<InType>(src);
if you need to check what the classes passed as template arguments actually can do (if they are arithmetic or additive or copy constructible e.g.) use Concepts from the C++20 standard
I have done a lot of research on this but I wasn't able to find a design pattern addressing the problem. This is a minimal description of what I'm trying to perform.
#include <iostream>
using namespace std;
template <class T, T default_value=T{}>
class A{
private:
T inclassValue;
public:
A(T icv):inclassValue{icv}{}
const T& operator[](int k){
if(k==1) return inclassValue;
return default_value;
}
};
struct two_int{int x;int y;};
int main(){
A<int> a{4};
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
/*
A<two_int> b{{3,5}};
cout << "b[0]=" << b[0].x << "," << b[0].y << endl;
cout << "b[1]=" << b[1].x << "," << b[1].y << endl;
*/
return 0;
}
The code will compile, link and output as expected
a[0]=0
a[1]=4
The compiler complains though and issues a warning for the line of code where default_value is used
return default_value;//Returning reference to local temporary object
which makes some sense. Uncommenting the last part in main and compiling, the compiler issue this time an error while building the template
template <class T, const T default_value= T{}>//A non-type template parameter cannot have type 'two_int'
while what I ideally hope for is
b[0]=0,0
b[1]=3,5
I was able to come up with a solution by adding an extra helper class, that will provide the default_value of T (as a static member), to the template arguments. I'm not convinced by the robustness of my trick and I was wondering if there exists a design pattern addressing this. The warning for types and the error for non-types. Also, I shall add that my primary goal is to be able to provide default_value at will (6 for int for example instead of 0).
Thanks
Not exactly sure what you're looking for, but perhaps a static helper finishing for creating a static default T could be useful:
template <typename T>
static const T& default_value() {
static const T* t = new T{};
return *t;
}
Note this will construct T at most once even across threads (in c++11), but still never destruct T. Since it's static, it's likely the lack of destruction is acceptable, but this of course depends on T.
Here is one version that forwards arguments to the constructor of a default_value stored as constexpr. You are quite limited here as to what is valid to pass as arguments (not sure exactly how limited) so it will depend on your use-case.
#include <iostream>
using namespace std;
template <class T, auto... Args>
class A{
private:
T inclassValue;
constexpr static T default_val = T{Args...}; // Changed to curly brackets here
public:
constexpr A(T icv):inclassValue{icv}{}
const T& operator[](int k){
if(k==1) return inclassValue;
return default_val;
}
};
struct two_int{int x;int y;};
int main(){
A<int> a{4};
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
A<two_int> b{{3,5}};
cout << "b[0]=" << b[0].x << "," << b[0].y << endl;
cout << "b[1]=" << b[1].x << "," << b[1].y << endl;
return 0;
}
I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).
I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).
Using typedef in C++ creates an alias for a type.
So:
typedef double Length;
typedef double Mass;
creates two aliases which can be intermixed. In other words we can pass a value of type Mass to a function that expects a value of type Length.
Is there a lightweight way of creating new types? I would like them to be double underneath but be "different" so that one can't be used in place of another.
I would prefer something lighter than creating a new class or struct. Also, I am aware of the dimensions lib in boost. This is more complex and does a lot more than I need.
BOOST_STRONG_TYPEDEF seems to be designed exactly for what you're looking for. I believe it does it's magic by creating a class and overloading the operators to make it behave like a builtin type, but I've not looked at it's implementation.
While BOOST_STRONG_TYPEDEF is a pretty simple solution, if you're mixing lengths and masses into more complicated units (e.g. in the physical sciences) then you might want to use Boost.Units.
One other possible answer in C++11 is to use enum class : type. This will allow you to do what you want but it has its own downsides. For example you would have to overload a lot of operators.
#include <iostream>
#include <string>
enum class A : int;
enum class B : int;
std::ostream& operator<<(std::ostream& os, const A& t){
os << static_cast<int>(t);
return os;
}
std::ostream& operator<<(std::ostream& os, const B& t){
os << static_cast<int>(t);
return os;
}
int test(A t){
std::cout << "A " << t << std::endl;
return 0;
}
int test(B t){
std::cout << "B " << t << std::endl;
return 0;
}
int main(){
A a{static_cast<A>(42)};
B b{static_cast<B>(0)};
test(a);
test(b);
}
This would give the output of:
A 42
B 0
Or you could just get the integer part like this
template<class T>
int GetInt(T t)
{
return static_cast<int>(t);
}
std::cout << "B " << GetInt(t) << std::endl;
If the Metaclasses proposal (p7070) goes through (right now it's still at revision0), then we shall be able to create strong typedefs using an empty metaclass. Proposed syntax:
$class strong_typedef { };
using Length = $double.as(strong_typedef);
using Mass = $double.as(strong_typedef);
Earliest we might see this would be C++20