Related
How can one do this, which is obviously impossible C++, in real C++?:
Type decodeUiEnum(UiEnum myEnum) { // impossible: cannot return a data type
// one switch statement to rule them all
switch(myEnum) {
case USER_SELECTED_GREYSCALE: return GreyscalePixel;
case USER_SELECTED_RGB: return RgbPixel;
...
}
}
void doSomeGraphicsMagic1(UiEnum myEnum) {
...
Foo<decodeUiEnum(myEnum)> a(...); // impossible: type not available at compile
// time
...
}
void doSomeGraphicsMagic2(UiEnum myEnum, int blah) {
...
Bar<int, decodeUiEnum(myEnum)> b(...); // impossible
...
}
and the like, so you can just add new types to the top switch statement and not have to modify the other code below it, so long as that code is suitably generic of course? As otherwise, you would need a switch statement within each function to do the necessary type mapping into the templates, which is not as much maintainable code, and lots of duplication. So more generally - if this is approaching it the wrong way, how do we fulfill that intended property of the code?
That is, what I want to do is, in a function taking an enum as parameter, instantiate a template type where the template parameter depends on the enum, without having a switch-on-enum in every function.
Yes it is actually possible.
Trick is based on partial template specification, this approach used by std::get
For example:
#include <iostream>
// specify an enumeration we will use as type index and related data types
enum class UiEnum {
GRAY_SCALE,
RGB_PIXEL
};
struct GreyscalePixel;
struct RgbPixel;
// make base template class
template<UiEnum _EV>
struct ui_enum_type {
};
// do partial type specification trick
// insert typedefs with data type we need for each enumeration value
template<>
struct ui_enum_type<UiEnum::GRAY_SCALE> {
typedef GreyscalePixel pixel_type;
};
template<>
struct ui_enum_type<UiEnum::RGB_PIXEL> {
typedef RgbPixel pixel_type;
};
// demo classes to demonstrate how trick is working at runtime
template<typename T>
struct demo_class {
};
template <>
struct demo_class<GreyscalePixel> {
demo_class()
{
std::cout << "GreyscalePixel" << std::endl;
}
};
template <>
struct demo_class<RgbPixel> {
demo_class()
{
std::cout << "RgbPixel" << std::endl;
}
};
// use swithc trick
static void swich_trick(std::size_t runtimeValue)
{
switch( static_cast<UiEnum>(runtimeValue) ) {
case UiEnum::GRAY_SCALE: {
demo_class< ui_enum_type<UiEnum::GRAY_SCALE>::pixel_type > demo1;
}
break;
case UiEnum::RGB_PIXEL: {
demo_class< ui_enum_type<UiEnum::RGB_PIXEL>::pixel_type > demo2;
}
break;
}
}
int main(int argc, const char** argv)
{
// Do runtime based on the trick, use enum instead of data type
for(std::size_t i=0; i < 2; i++) {
swich_trick(i);
}
return 0;
}
In any case my suggestion - use classic polymorphism instead of template meta-programming over complication. Most modern compilers doing de-virtualization during optimization. For example:
#include <iostream>
#include <memory>
#include <unordered_map>
enum class UiEnum {
GRAY_SCALE,
RGB_PIXEL
};
class GraphicsMagic {
GraphicsMagic(const GraphicsMagic&) = delete;
GraphicsMagic& operator=(const GraphicsMagic&) = delete;
protected:
GraphicsMagic() = default;
public:
virtual ~GraphicsMagic( ) = default;
virtual void doSome() = 0;
};
class GreyscaleGraphicsMagic final: public GraphicsMagic {
public:
GreyscaleGraphicsMagic():
GraphicsMagic()
{
}
virtual void doSome() override
{
std::cout << "GreyscalePixel" << std::endl;
}
};
class RgbGraphicsMagic final: public GraphicsMagic {
public:
RgbGraphicsMagic():
GraphicsMagic()
{
}
virtual void doSome() override
{
std::cout << "RgbPixel" << std::endl;
}
};
int main(int argc, const char** argv)
{
std::unordered_map< UiEnum, std::shared_ptr< GraphicsMagic > > handlers;
handlers.emplace(UiEnum::GRAY_SCALE, new GreyscaleGraphicsMagic() ) ;
handlers.emplace(UiEnum::RGB_PIXEL, new RgbGraphicsMagic() );
for(std::size_t i=0; i < 2; i++) {
handlers.at( static_cast<UiEnum>(i) )->doSome();
}
return 0;
}
You could use std::variant, and then have consuming code std::visit that variant.
First we want a template for "pass a type as a parameter"
template <typename T>
struct tag {
using type = T;
};
Then we define our variant and the factory for it.
using PixelType = std::variant<tag<GreyscalePixel>, tag<RgbPixel>>;
PixelType decodeUiEnum(UiEnum myEnum) {
switch(myEnum) {
case USER_SELECTED_GREYSCALE: return tag<GreyscalePixel>{};
case USER_SELECTED_RGB: return tag<RgbPixel>{};
...
}
}
Now our methods can be written as visitors over PixelType
void doSomeGraphicsMagic1(UiEnum myEnum) {
std::visit([](auto t){
using Pixel = decltype(t)::type;
Foo<Pixel> a(...);
}, decodeUiEnum(myEnum));
}
int doSomeGraphicsMagic2(UiEnum myEnum, int blah) {
return std::visit([blah](auto t){
using Pixel = decltype(t)::type;
Bar<int, Pixel> a(...);
return a.frob();
}, decodeUiEnum(myEnum));
}
I'm trying to refactor some code. Basically is a state machine based with enum.
There are a lot of switch statements and functions that got called with different names and ambiguations.
Since they force me to keep the enum, I would like to refactor it using template. Basically I would like to use template to implement polymorphism. Since the states are limited there should be a way but I cannot find the best one.
#include <iostream>
enum class AnimalType
{
Dog,
Cat
};
template<AnimalType T>
void Foo()
{
std::cout << "Unknown animal\n";
}
template<>
void Foo<AnimalType::Dog>()
{
std::cout << "I'm a dog\n";
}
template<>
void Foo<AnimalType::Cat>()
{
std::cout << "I'm a cat\n";
}
int main()
{
AnimalType CurrentAnimal = AnimalType::Dog;
// Foo<CurrentAnimal>(); Won't compile
return 0;
}
You need a compile time evaluatable constant, this will work
int main()
{
constexpr auto CurrentAnimal = AnimalType::Dog;
Foo<CurrentAnimal>();
return 0;
}
or directly use
Foo<AnimalType::Dog>();
Note : you can't use your construct to make decissions at runtime.
Templates only lead to compile time polymorphism
As mentioned by #P Kramer's answer:
Note : you can't use your construct to make decissions at runtime. Templates only lead to compile time polymorphism.
You can't do that, but you can use the Compile-Time Dispatch and runtime parameter by passing the desired value as parameter while they are separated by Function Template Specialization. For example turn your enumerations value into actual types:
struct animal_t
{
std::string const name;
explicit animal_t(std::string const& name_)
: name(name_)
{
}
auto operator()() const
{
return name;
}
};
struct dog_t final : animal_t
{
using animal_t::animal_t;
};
struct cat_t final : animal_t
{
using animal_t::animal_t;
};
They you are able to specialize the function template:
/*!
*
* Other Programmer(s) interface
*
*/
template<typename Animal>
auto function(Animal const&)
{
assert(false);
}
/*!
*
* Implementation
*
*/
template<>
auto function(cat_t const& animal)
{
return animal();
}
template<>
auto function(dog_t const& animal)
{
return animal();
}
Now user (other programmer) of your library could easily interact with it for example by a GUI library:
QObject::connect(button1, &QPushButton::clicked, &application, [] {
cat_t cat("Some Cat");
auto const message = QString::fromStdString(function(cat));
QMessageBox::information(nullptr, " ", message);
});
QObject::connect(button2, &QPushButton::clicked, &application, [] {
dog_t dog("Some Dog");
auto const message = QString::fromStdString(function(dog));
QMessageBox::information(nullptr, " ", message);
});
Result: just for copy/past: runtime_dispatch_v1
We have
enum Enum {A,B,C,D,E,F,G,H, NumEnums};
class Base {};
template <Enum...> class Thing : public Base {};
and the function
Base* create (std::list<Enum>& input);
is to create an object of the type that corresponds to input. For example,
if input = {A,E,C,G,D};, then the output shall be of type Thing<A,E,C,G,D>* (let's forget the sorting here). Now I know input is obtained during run-time, but by doing a search, the output can be obtained fairly quickly. If Thing had only one parameter (i.e. input has size() one), then the simple
template <int N>
Base* createHelper (const std::list<Enum>& input) {
const Enum En = static_cast<Enum>(N);
if (input.front() == En)
return new Thing<En>;
return createHelper<N+1>(input);
}
template <>
Base* createHelper<NumEnums> (const std::list<Enum>&) {
return nullptr;
}
Base* create (const std::list<Enum>& input) {
return createHelper<0>(input);
}
will do. I tried to generalize the above to any size list (the size would have to be determined during run-time through a similar recursion as above, but that should be fairly quick too). But I got totally lost on how. So I tried to examine the structure of the naïve method:
#include <iostream>
#include <list>
#include <type_traits>
#include <typeinfo>
enum Enum {A,B,C,D,E,F,G,H, NumEnums};
class Base {
public:
virtual void print() const = 0;
};
template <Enum...> class Thing : public Base {
virtual void print() const override {std::cout << typeid(*this).name() << '\n';}
};
Base* create (std::list<Enum>& input) {
if (input.front() == A) {
input.pop_front();
if (input.empty())
return new Thing<A>;
else {
if (input.front() == A) {
input.pop_front();
if (input.empty())
return new Thing<A,A>;
else {
// ....
}
}
else if (input.front() == B) {
input.pop_front();
if (input.empty())
return new Thing<A,B>;
else {
// ....
}
}
}
}
else if (input.front() == B) {
// similar
}
// ...
}
int main() {
std::list<Enum> userInput = {A,B};
// Wish to construct an instance of Thing<A,B> (efficiently).
Base* thing = create(userInput);
thing->print(); // Thing<A,B>
}
I figured I could put this in recursive form. But I cannot think of it. I know the one-dimensional case can be generalized, but I need help here. Or perhaps there is a better way to do it altogether? Once it works, it should not take anymore than a fraction of a second for the create function to return, assuming NumEnums is a decent size and the Thing class has just several template arguments, and not hundreds.
Edit: Turns out, there may be a viable solution here:
Create an associate array between your key and a type factory class.
Dynamically allocate any variables you may need from the type factory once you have it selected (preferably using std::unique_ptr).
The end result may end of looking like this:
std::unordered_map<std::string, type_allocator> str_to_type;
str_to_type["a"] = type_allocator(int); //where type_allocator derives the type of the class from the input variable.
auto variable = str_to_type[input].allocate();
For specific size, if you compute a single index, you may dispatch at runtime to the correct compile time function:
template <std::size_t N>
std::unique_ptr<Base> make_thing3()
{
constexpr Enum a2 = Enum(N % NumEnums);
constexpr Enum a1 = Enum((N / NumEnums) % NumEnums);
constexpr Enum a0 = Enum((N / NumEnums / NumEnums) % NumEnums);
return std::make_unique<Thing<a0, a1, a2>>();
}
template <std::size_t... Is>
std::unique_ptr<Base> make_thing3(std::size_t index, std::index_sequence<Is...>)
{
using maker = std::unique_ptr<Base>();
maker* fs[] = {&make_thing3<Is>...};
return fs[index]();
}
std::unique_ptr<Base> make_thing3(const std::array<Enum, 3u>& a)
{
std::size_t index = 0;
for (Enum e : a) {
index *= NumEnums;
index += e;
}
constexpr std::size_t total = NumEnums * NumEnums * NumEnums;
return make_thing3(index, std::make_index_sequence<total>{});
}
Live Demo
Note: I had to change size of Enum, and reduce my example from make_thing5 to make_thing3 due to compiler limit (not sure if it came from the site or if it is true limits)
This solution shows that though the compile-time is long (due to the many template instantiations), the run-time look-up is instant. The compiler limits is 3 enum values as input though. The empty input case is handled too (the return type being Thing<>*).
#include <iostream>
#include <list>
#define show(variable) std::cout << #variable << " = " << variable << std::endl;
enum Enum {A,B,C,D,E,F,G,H, NumEnums};
class Base {
public:
virtual void print() const = 0;
};
template <Enum... Es> class Thing : public Base {
virtual void print() const override {
const std::list<int> a = {((std::cout << Es << ' '), 0)...};
std::cout << "\nPack size = " << sizeof...(Es) << '\n';
}
};
template <int N, int Size, Enum... Es>
struct Create {
static Base* execute (std::list<Enum>& input) {
const Enum En = static_cast<Enum>(N);
if (input.front() == En) {
input.pop_front();
return Create<0, Size-1, Es..., En>::execute(input);
}
return Create<N+1, Size, Es...>::execute(input);
}
};
template <int N, Enum... Es>
struct Create<N, 0, Es...> {
static Base* execute (std::list<Enum>&) {return new Thing<Es...>;}
};
template <int Size, Enum... Es>
struct Create<NumEnums, Size, Es...> {
static Base* execute (std::list<Enum>&) {return nullptr;} // This will never be reached
};
template <int Size>
Base* do_create (std::list<Enum>& input) {
if (input.size() == Size)
return Create<0, Size>::execute(input);
return do_create<Size+1>(input);
}
template <>
Base* do_create<4> (std::list<Enum>&) {
std::cout << "Cannot exceed 3 values.\n";
return nullptr;
}
Base* create (std::list<Enum>& input) {
return do_create<0>(input);
}
int main() {
std::list<Enum> input = {E,A,F};
Base* thing = create(input);
thing->print(); // 4 0 5
input = {};
create(input)->print(); // Pack size = 0.
}
I have an enum class with two values, and I want to create a method which receives a value
and returns the other one. I also want to maintain type safety(that's why I use enum class instead of enums).
http://www.cplusplus.com/doc/tutorial/other_data_types/ doesn't mention anything about methods
However, I was under the impression that any type of class can have methods.
No, they can't.
I can understand that the enum class part for strongly typed enums in C++11 might seem to imply that your enum has class traits too, but it's not the case. My educated guess is that the choice of the keywords was inspired by the pattern we used before C++11 to get scoped enums:
class Foo {
public:
enum {BAR, BAZ};
};
However, that's just syntax. Again, enum class is not a class.
While the answer that "you can't" is technically correct, I believe you may be able to achieve the behavior you're looking for using the following idea:
I imagine that you want to write something like:
Fruit f = Fruit::Strawberry;
f.IsYellow();
And you were hoping that the code looks something like this:
enum class Fruit : uint8_t
{
Apple,
Pear,
Banana,
Strawberry,
bool IsYellow() { return this == Banana; }
};
But of course, it doesn't work, because enums can't have methods (and 'this' doesn't mean anything in the above context)
However, if you use the idea of a normal class containing a non-class enum and a single member variable that contains a value of that type, you can get extremely close to the syntax/behavior/type safety that you want. i.e.:
class Fruit
{
public:
enum Value : uint8_t
{
Apple,
Pear,
Banana,
Strawberry
};
Fruit() = default;
constexpr Fruit(Value aFruit) : value(aFruit) { }
#if Enable switch(fruit) use case:
// Allow switch and comparisons.
constexpr operator Value() const { return value; }
// Prevent usage: if(fruit)
explicit operator bool() const = delete;
#else
constexpr bool operator==(Fruit a) const { return value == a.value; }
constexpr bool operator!=(Fruit a) const { return value != a.value; }
#endif
constexpr bool IsYellow() const { return value == Banana; }
private:
Value value;
};
Now you can write:
Fruit f = Fruit::Strawberry;
f.IsYellow();
And the compiler will prevent things like:
Fruit f = 1; // Compile time error.
You could easily add methods such that:
Fruit f("Apple");
and
f.ToString();
can be supported.
Concentrating on the description of the question instead of the title a possible answer is
struct LowLevelMouseEvent {
enum Enum {
mouse_event_uninitialized = -2000000000, // generate crash if try to use it uninitialized.
mouse_event_unknown = 0,
mouse_event_unimplemented,
mouse_event_unnecessary,
mouse_event_move,
mouse_event_left_down,
mouse_event_left_up,
mouse_event_right_down,
mouse_event_right_up,
mouse_event_middle_down,
mouse_event_middle_up,
mouse_event_wheel
};
static const char* ToStr (const type::LowLevelMouseEvent::Enum& event)
{
switch (event) {
case mouse_event_unknown: return "unknown";
case mouse_event_unimplemented: return "unimplemented";
case mouse_event_unnecessary: return "unnecessary";
case mouse_event_move: return "move";
case mouse_event_left_down: return "left down";
case mouse_event_left_up: return "left up";
case mouse_event_right_down: return "right down";
case mouse_event_right_up: return "right up";
case mouse_event_middle_down: return "middle down";
case mouse_event_middle_up: return "middle up";
case mouse_event_wheel: return "wheel";
default:
Assert (false);
break;
}
return "";
}
};
There is a pretty compatible ability(§) to refactor an enum into a class without having to rewrite your code, which means that effectively you can do what you were asking to do without too much editing.
(§) as ElementW points out in a comment, type_traits dependent code will not work, so e.g. one cannot use auto, etc. There may be some way of handling such stuff, but in the end one is converting an enum into a class, and it is always a mistake to subvert C++
the enum struct and enum class specifications are about scoping so not part of this.
Your original enum is e.g. 'pet' (this is as an example only!).
enum pet {
fish, cat, dog, bird, rabbit, other
};
(1) You modify that to eg petEnum (so as to hide it from your existing code).
enum petEnum {
fish, cat, dog, bird, rabbit, other
};
(2) You add a new class declaration below it (named with the original enum)
class pet {
private:
petEnum value;
pet() {}
public:
pet(const petEnum& v) : value{v} {} //not explicit here.
operator petEnum() const { return value; }
pet& operator=(petEnum v) { value = v; return *this;}
bool operator==(const petEnum v) const { return value == v; }
bool operator!=(const petEnum v) const { return value != v; }
// operator std::string() const;
};
(3) You can now add whatever class methods you like to your pet class.
eg. a string operator
pet::operator std::string() const {
switch (value) {
case fish: return "fish";
case cat: return "cat";
case dog: return "dog";
case bird: return "bird";
case rabbit: return "rabbit";
case other: return "Wow. How exotic of you!";
}
}
Now you can use eg std::cout...
int main() {
pet myPet = rabbit;
if(myPet != fish) {
cout << "No splashing! ";
}
std::cout << "I have a " << std::string(myPet) << std::endl;
return 0;
}
As mentioned in the other answer, no. Even enum class isn't a class.
Usually the need to have methods for an enum results from the reason that it's not a regular (just incrementing) enum, but kind of bitwise definition of values to be masked or need other bit-arithmetic operations:
enum class Flags : unsigned char {
Flag1 = 0x01 , // Bit #0
Flag2 = 0x02 , // Bit #1
Flag3 = 0x04 , // Bit #3
// aso ...
}
// Sets both lower bits
unsigned char flags = (unsigned char)(Flags::Flag1 | Flags::Flag2);
// Set Flag3
flags |= Flags::Flag3;
// Reset Flag2
flags &= ~Flags::Flag2;
Obviously one thinks of encapsulating the necessary operations to re-/set single/group of bits, by e.g. bit mask value or even bit index driven operations would be useful for manipulation of such a set of 'flags'.
The c++11 struct/class specification just supports better scoping of enum values for access. No more, no less!
Ways to get out of the restriction you cannot declare methods for enum (classes) are , either to use a std::bitset (wrapper class), or a bitfield union.
unions, and such bitfield unions can have methods (see here for the restrictions!).
I have a sample, how to convert bit mask values (as shown above) to their corresponding bit indices, that can be used along a std::bitset here: BitIndexConverter.hpp
I've found this pretty useful for enhancing readability of some 'flag' decison based algorithms.
It may not fulfill all your needs, but with non-member operators you can still have a lot of fun. For example:
#include <iostream>
enum class security_level
{
none, low, medium, high
};
static bool operator!(security_level s) { return s == security_level::none; }
static security_level& operator++(security_level& s)
{
switch(s)
{
case security_level::none: s = security_level::low; break;
case security_level::low: s = security_level::medium; break;
case security_level::medium: s = security_level::high; break;
case security_level::high: break;
}
return s;
}
static std::ostream & operator<<(std::ostream &o, security_level s)
{
switch(s)
{
case security_level::none: return o << "none";
case security_level::low: return o << "low";
case security_level::medium: return o << "medium";
case security_level::high: return o << "high";
}
}
This allows code like
security_level l = security_level::none;
if(!!l) { std::cout << "has a security level: " << l << std::endl; } // not reached
++++l;
if(!!l) { std::cout << "has a security level: " << l << std::endl; } // reached: "medium"
Based on jtlim's answer
Idea (Solution)
enum ErrorType: int {
noConnection,
noMemory
};
class Error {
public:
Error() = default;
constexpr Error(ErrorType type) : type(type) { }
operator ErrorType() const { return type; }
constexpr bool operator == (Error error) const { return type == error.type; }
constexpr bool operator != (Error error) const { return type != error.type; }
constexpr bool operator == (ErrorType errorType) const { return type == errorType; }
constexpr bool operator != (ErrorType errorType) const { return type != errorType; }
String description() {
switch (type) {
case noConnection: return "no connection";
case noMemory: return "no memory";
default: return "undefined error";
}
}
private:
ErrorType type;
};
Usage
Error err = Error(noConnection);
err = noMemory;
print("1 " + err.description());
switch (err) {
case noConnection:
print("2 bad connection");
break;
case noMemory:
print("2 disk is full");
break;
default:
print("2 oops");
break;
}
if (err == noMemory) { print("3 Errors match"); }
if (err != noConnection) { print("4 Errors don't match"); }
Yes, they can, but you need to make a wrapper class, for example:
#include <iostream>
using namespace std;
class Selection {
public:
enum SelectionEnum {
yes,
maybe,
iDontKnow,
canYouRepeatTheQuestion
};
Selection(SelectionEnum selection){value=selection;};
string toString() {
string selectionToString[4]={
"Yes",
"Maybe",
"I don't know",
"Can you repeat the question?"
};
return selectionToString[value];
};
private:
SelectionEnum value;
};
int main(){
Selection s=Selection(Selection::yes);
cout<<s.toString()<<endl;
return 0;
}
Is it possible to access the this pointer in non-static context and use something else in static context automatically? Do you know any macro or template magic?
#define LOG std::cout << _is_the_this_pointer_available_ ? this : 0
class Foo {
void test() {
LOG;
}
};
void staticTest() {
LOG;
}
Do you know any macro or template magic?
Honestly, I wouldn't do this with a macro. When something can be done without macros, I'd suggest to prefer avoiding them. Here is a possible solution based on overloading, CRTP, and inheritance (no macros):
int get_this() { return 0; }
template<typename T>
struct get_this_helper
{
T* get_this() { return static_cast<T*>(this); }
};
The only overhead is that you have to make your classes derive from the proper specialization of get_this_helper<>, as shown below:
#include <iostream>
#define LOG std::cout << get_this() << std::endl;
class Foo : public get_this_helper<Foo> {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// This is the only thing that requires
// being changed wrt your version of Foo
public:
void test() {
LOG;
}
};
void staticTest() {
LOG;
}
Here is a simple test program:
int main()
{
Foo f;
f.test();
staticTest();
}
And a live example.
I am using the following technique to write this pointer to a log:
#define GET_THIS() __if_exists(this) { this; } __if_not_exists(this) { nullptr; }
However it is Microsoft specific.
#define LOG std::cout << isThisAvailable()
bool isThisAvailable() { return false; }
struct X
{
bool isThisAvailable() { return true; }
void test() { LOG; }
};
void staticTest()
{
LOG;
}
Calling isThisAvailable inside the class will return true. Calling outside the class context will call the free function and return false.