With an enum Foo::Values and a class Bar outside of Foo, can I inject all values of the enum into class scope without redefining the type?
namespace Foo{
enum Values{
zero, one, two
};
}
struct Bar{
typedef Foo::Values Values; //Doesn't work, but is what I'd like to do
using Foo::Values; //Or this
}
So that these are valid:
Foo::Values val = Bar::zero;
assert(std::is_same<Foo::Values, Bar::Values>::value);
Is this possible?
This way:
using Values = Foo::Values;
Extracting the values is possible only one by one:
static constexpr Values zero = Foo::zero;
static constexpr Values one = Foo::one;
static constexpr Values two = Foo::two;
Check:
#include <iostream>
#include <type_traits>
namespace Foo {
enum Values { zero, one, two };
}
struct Bar {
using Values = Foo::Values;
static constexpr Values zero = Foo::zero;
static constexpr Values one = Foo::one;
static constexpr Values two = Foo::two;
};
int main() {
Foo::Values val = Bar::zero;
std::cout << std::is_same<Foo::Values, Bar::Values>::value;
}
Output:
1
Related
I have a static array in a class and an enum for the index of such array.
enum MyEnum
{
FIRST = 0,
SECOND,
LAST
}
class MyClass
{
public:
static string names[LAST];
}
I'd like to initialize my static array to associate a value of the array to each enum type like this:
names[FIRST] = "First";
names[SECOND] = "Second";
I know that I can initialize the array upon declaration like this static string names[] = {"First", "Second"}, but I want to explicitly assign the value to the corresponding enum to avoid errors.
In Java, there's a static block where you can do this kind of initialization, but I don't think that this is the case in C++. Is there an elegant way of doing this? I can't use std on my project, so the solution has to avoid any library usage.
Thanks in advance.
Write a function to initialize it. Function can't return an array - if you want to use an array, return a whole object that has an array inside it. Or you can return something dynamically allocated, a map or a vector.
#include <array>
#include <string>
enum MyEnum {
FIRST = 0,
SECOND,
LAST
};
std::array<std::string, LAST> construct_names() {
std::array<std::string, LAST> r;
r[FIRST] = "first";
r[SECOND] = "second";
return r;
}
static auto names = construct_names();
I can't use std on my project, so the solution has to avoid any library usage.
Roll your own types.
enum MyEnum {
FIRST = 0,
SECOND,
LAST
};
template<typename T, unsigned N>
struct MyArray {
T data[N];
T &operator[](unsigned i) {
return data[i];
}
};
MyArray<const char *, LAST> construct_names() {
MyArray<const char *, LAST> r;
r[FIRST] = "first";
r[SECOND] = "second";
return r;
}
static auto names = construct_names();
You may also want to read How to initialize private static members in C++? or similar, as for class initialization you need to do like, there will be some type repetition:
class MyClass {
public:
static MyArray<const char *, LAST> names;
};
MyArray<const char *, LAST> MyClass::names = construct_names();
Yes you can do it in simple way using __attribute__((init_priority(101))) and __attribute__((constructor(102)))
#include <string>
#include <iostream>
using namespace std;
enum MyEnum
{
FIRST = 0,
SECOND,
LAST
};
class MyClass
{
public:
static string names[LAST];
};
__attribute__((init_priority(101))) string MyClass::names[LAST];
__attribute__((constructor(102))) void foo()
{
MyClass::names[FIRST] = "First";
MyClass::names[SECOND] = "Second";
}
int main()
{
MyClass m;
for (int i = 0; i < LAST; i++) {
cout << m.names[i] << "\n";
}
}
Output:
First
Second
Explanation in simple:
Before even code loads, first it initialize string MyClass::names[LAST]; because we added __attribute__((init_priority(101))) then it calls foo() automatically, The function name can be any it does not matter, it can be init as well no need to be foo. The order of initialization is based on number 101 and 102. If we change the order then it wont work.
For more info refer: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-init_005fpriority-variable-attribute
Declaimer: This initialization is not bound to the class, if you keep on adding like this for all the classes then you are in big trouble and you need to keep on maintain a list of orders. This inits are for the entire binary or library
template <typename StoredT>
class InternalObject {
public:
using RefCountT = unsigned short;
template <typename... CtorTs>
static void* emplace(CtorTs&&...);
Types type;
RefCountT reference_count;
bool is_immovable;
StoredT stored_value;
InternalObject();
InternalObject(StoredT);
~InternalObject();
};
My class has a member StoredT stored_value which I would like to be able to construct using emplace and return a void* to it.
However, if I want to do this, I would have to do InternalObject<StoredT> *io_ptr = new InternalObject<StoredT>; which would force me to default-construct stored_value.
The solution I attempted was to allocate the appropriate amount of space as an array of unsigned char (the returned pointer is a heap pointer). Then, I tried to increment the pointer by appropriate amounts and modify the value there.
A more reproducible & complete example which does not produce a valid (non-POD) value for two.
#include <iostream>
#include <vector>
struct S {
int one;
std::vector<int> two;
};
int main() {
unsigned char *s_ptr = new unsigned char[sizeof(S)];
S *s = reinterpret_cast<S*>(s_ptr);
*s_ptr = 100; // Fine
std::vector<int> *vec_ptr = reinterpret_cast<std::vector<int>*>(s_ptr + sizeof(int));
*vec_ptr = {5,6,7};
std::cout << s->two.capacity() << "\n"; // big ol' number
return 0;
}
Consider using std::optional<StoredT>, which will allow you to defer the construction of the StoredT that you want to hold:
#include <optional>
template <typename StoredT>
class InternalObject {
public:
using RefCountT = unsigned short;
template <typename... CtorTs>
void emplace(CtorTs&&... args) {
stored_value.emplace(args...);
}
Types type;
RefCountT reference_count;
bool is_immovable;
std::optional<StoredT> stored_value;
InternalObject();
InternalObject(StoredT);
~InternalObject();
};
I am abstracting my problem now but I am in this kind of situation.
Let's say I have 2 enums that are in the same namespace.
namespace some_namespace {
enum class Something{
S,
O,
M,
E,
T,
H,
I,
N,
G
};
enum class Else{
E,
L,
S
};
}
Now let's create 2 structs which have as a static field some value of these enums.
struct SomeStruct{
static constexpr int enumValue = static_cast<int>(some_namespace::Something::T);
};
struct AnotherStruct {
static constexpr int enumValue = static_cast<int>(some_namespace::Something::O);
};
How can I check whether the enumValues of this 2 structs are from the same enum class or not? I think I shall give some values to my enum fields and use some bitwise operator on enum values to distinguish? Can someone help? thanks)
Using just the static_casted enumValue it is not possible to distinguish the originating enum(as pointed out by #Sam). What you can instead do is introduce a new field that stores the underlying enum class type and leverage that to make the distinction.
enum class E1{ One, Two };
enum class E2{Three, Four };
struct SomeStruct{
static constexpr int enumValue = static_cast<int>(E1::One);
using UnderlyingT = E1;
};
struct AnotherStruct {
static constexpr int enumValue = static_cast<int>(E2::Three);
using UnderlyingT = E2;
};
static_assert(!std::is_same_v<SomeStruct::UnderlyingT, AnotherStruct::UnderlyingT>);
Code Link
As already indicated in the comments, you don't want to convert your enum to an int if you still want to know the type.
There might be some reasons to keep the type and the scoping while wanting to implicit conversion to the underlying type.
What you could do is to wrap the enum into a class that converts to both the underlying type AND the actual enum.
#include <type_traits>
template<typename TEnum>
class ImplicitEnumConverter final
{
public:
TEnum e;
using TUnderlyingType = std::underlying_type_t<TEnum>;
constexpr ImplicitEnumConverter(TEnum e) : e{e} {}
constexpr operator TUnderlyingType() const noexcept
{
return static_cast<TUnderlyingType>(e);
}
constexpr operator TEnum() const noexcept
{
return e;
}
};
struct SomeStruct{
static constexpr auto enumValue = ImplicitEnumConverter{some_namespace::Something::T};
};
Code at compiler-explorer
This way, you are able to keep all the type-safe information where this is relevant AND you are able to convert it implicitly to an int.
The answer was simpler than I thought.
So I declare enum like this.
namespace some_namespace {
enum class Something{
S = 0,
O = 2,
M = 4,
E = 6,
T = 8,
H = 10,
I = 12,
N = 14,
G = 16
};
enum class Else{
E = 1,
L = 3,
S = 5
};
}
And then this leads me to check whether two integer values have the same parity or not . Thus
if((SomeStruct::enum_value + AnotherStruct::enum_value) % 2 == 0) {
// Same enum
} else {
// not same enum.
}
I want to calculate factorial at the compile-time. I found some way to solve the problem, but I want to know if there any another solution for this problem without using enum s. Here the solution using enum s.
#include <iostream>
template <int n>
struct fact
{
enum{value = n*fact<n-1>::value};
};
template<>
struct fact<1>
{
enum{value = 1};
};
int main()
{
std::cout << fact<10>::value;
}
If there is no another solution, please describe why the enum s are must.
While there are alternative notations, It's written that way because more compilers accept that enum-style notation. The language supports const integral-type class members with an inline initialization, but some compilers aren't compliant with the standard in that regard. On compilers that are compliant in this regard, the following works just fine:
#include <iostream>
template <unsigned int n>
struct fact
{
static const unsigned int value = n*fact<n-1>::value;
};
template<>
struct fact<0>
{
static const unsigned int value = 1;
};
int main()
{
std::cout << fact<10>::value << "\n";
}
Replace,
enum{value};
with,
static int const value; // or unsigned int
enums are must because they suppose to be resolved at compile time. Which assures that whatever result you calculated must have been done at compile time. Other such type is static int const (means any integral type).
To illustrate:
enum E {
X = strlen(s); // is an error, because X is a compile time constant
};
Alternatively, you can use static const members:
template <unsigned int n>
struct fact { static const unsigned int value = n * fact<n-1>::value; }
Why do people use enums in C++ as constants when they can use const?
Bruce Eckel gives a reason in Thinking in C++:
In older versions of C++, static const was not supported inside classes. This meant that const was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untagged enum with no instances. An enumeration must have all its values established at compile time, it’s local to the class, and its values are available for constant expressions. Thus, you will commonly see:
#include <iostream>
using namespace std;
class Bunch {
enum { size = 1000 };
int i[size];
};
int main() {
cout << "sizeof(Bunch) = " << sizeof(Bunch)
<< ", sizeof(i[1000]) = "
<< sizeof(int[1000]) << endl;
}
Enums are distinct types, so you can do type-oriented things like overloading with them:
enum Color { Red,Green,Blue };
enum Size { Big,Little };
void f( Color c ) {
}
void f( Size s ) {
}
int main() {
f( Red );
f( Big );
}
An enumeration implies a set of related constants, so the added information about the relationship must be useful in their model of the problem at hand.
There's a historical reason too when dealing with template metaprogramming. Some compilers could use values from an enum, but not a static const int to instantiate a class.
template <int N>
struct foo
{
enum { Value = foo<N-1>::Value + N };
};
template <>
struct foo<0>
{
enum { Value = 0; }
};
Now you can do it the more sensible way:
template <int N>
struct foo
{
static const int Value = foo<N-1>::Value + N;
};
template <>
struct foo<0>
{
static const int Value = 0;
};
Another possible reason, is that a static const int may have memory reserved for it at runtime, whereas an enum is never going to have an actual memory location reserved for it, and will be dealt at compile time. See this related question.
Enums are more descriptive when used. Consider:
int f(int fg, int bg)
versus
int f(COLOR fg, COLOR bg)
In addition, enums give a bit more type-safety, because
integers are not implicitly convertible to enum types
enum of one type is not implicitly convertible to enum of another type
I like the automatic behavior that can be used with enums, for example:
enum {NONE, START, HEY, HO, LAST};
Then it is easy to loop until LAST, and when a new state (or whatever is represented) is added, the logic adapts.
for (int i = NONE; i < LAST; i++)
{
// Do stuff...
}
Add something...
enum {NONE, START, HEY, WEE, HO, LAST};
The loop adapts...
Before compiler vendors implemented the ISO/IEC 14882:1998 C++ standard, this code to define a constant in a class scope resulted in a compile error:
class Foo {
static const int MAX_LEN = 80;
...
};
If the constant is an integer type, a kludgy work around is define it in an enum inside the class:
class Foo {
enum {
MAX_LEN = 80
};
...
};
enums also can be used as a type name. So you can define a function that takes an enum as a parameter, which makes it more clear what kinds of values should be given as arguments to the function, as compared to having the values defined as const variables and the function accepting just "int" as an argument.
Consider:
enum my_new_fangled_type {
baz = 0,
meh = 1
};
void foo (my_new_fangled_type bar) // bar can be a value listed in the enum
{
...
}
versus:
int const baz = 0;
int const meh = 1;
void foo (int bar) // what are valid values for bar?
{
...
}
Some debuggers will show the enumeration name instead of its value when debugging. This can be very helpful. I know that I would rather see day_of_week = MONDAY than day_of_week = 1.
It's partly because older compilers did not support the declaration of a true class constant
class C
{
const int ARealConstant = 10;
};
so had to do this
class C
{
enum { ARealConstant = 10 };
};
For this reason, many portable libraries continue to use this form.
The other reason is that enums can be used as a convenient syntactic device to organise class constants into those that are related, and those that are not
class DirectorySearcher
{
enum options
{
showFiles = 0x01,
showDirectories = 0x02,
showLinks = 0x04,
};
};
vs
class Integer
{
enum { treatAsNumeric = true };
enum { treatAsIntegral = true };
enum { treatAsString = false };
};
Using an enum documents the valid choices in a terse manner and allows the compiler to enforce them.
If they are using enum store global constants, like Pi, for example, then I don't know what their goal is.
One reason is that const requires more typing:
enum { Val1, Val2, Val3 };
...versus...
const int Val1=0, Val2=1, Val3=2;