C++ - Use enum from template class without template parameter - c++

template<typename T> class SomeClass{
public:
enum SomeEnum{ SOME_FLAG};
};
SomeClass::SomeEnum some_enum = SomeClass::SomeEnum::SOME_FLAG; //NO
SomeClass<int>::SomeEnum some_enum = SomeClass::SomeEnum::SOME_FLAG; //NO
SomeClass<int>::SomeEnum some_enum = SomeClass<int>::SomeEnum::SOME_FLAG; //YES
This won't compile because
class SomeClass used without template parameters
Is there no way / workaround to use it without template parameter, kinda make that enum global for that class, so it doesn't depend on the parameter.
It's not that I can't type them but they can be long and complicated, the code will be harder to read and I can't use something like auto here.
(I'm new to templates so sorry if this question is lame.)

If you want to enclose your enum in a class definition for reasons (I cannot say what's the real problem), you can still introduce one more class that isn't a class template and contains the enum, then inherit from that with your class template. That's all.
As an example:
struct SomeBase {
enum SomeEnum { SOME_FLAG };
};
template<typename>
struct SomeClass: SomeBase {
// ...
};
Use this:
SomeBase::SomeEnum::SOME_FLAG;
Instead of this:
SomeClass::SomeEnum::SOME_FLAG;
Whenever you want to access the enum directly.
Something like the following remains valid anyway:
SomeClass<void>::SomeEnum foo = SomeClass<void>::SomeEnum::SOME_FLAG;

using MySomeClass = SomeClass<int>;
MySomeClass::SomeEnum foo = MySomeClass::SomeEnum::SOME_FLAG;

Related

Possibility of defining one variable with multiple types based on a macro

I am wondering if it is possible to do:
class MyClass
{
public:
MyClass();
...
#if defined USE_TYPE_ONE
static TypeOne myVariable;
#else
static TypeTwo myVariable;
#endif USE_TYPE_ONE
};
The reason is that I have two classes, TypeOne & TypeTwo, with same function variables but different implementations and
I don't want to use macro in every place that myVariable is called.
EDIT
Thanks for prompt comments and answer. I have to mention that MyClass has been used a lot with different classes. That is why I would like to avoid template. Because even using template class with default template argument type, I have to use <> (change many other places) for other places that I use MyClass without need of TypeOne.
You can use a template as suggested but if you just need to switch between two types according to a condition and you have access to C++11 <type_traits> (otherwise consider updating your compiler), then you could use std::conditional:
#include <type_traits>
constexpr bool USE_TYPE_ONE = true;
struct TypeOne { };
struct TypeTwo { };
class MyClass {
using Type = std::conditional<USE_TYPE_ONE, TypeOne, TypeTwo>::type;
static Type myVariable;
};
As pointed out in the comments, you don't have to use macro's, you can use a templated class to achieve this:
template <typename T>
class MyClass
{
public:
MyClass();
static T myVariable;
};
Then instantiate it how you like (for example for int types):
MyClass<int>::myVariable;
Why wouldn't it be possible? It's totally possible. Of course you need to pass that preproc variable in the build somehow, and it'll be defined as that type for all code in the program...but it is indeed totally possible.

static non-template method in template class

I want to add a static function to a template class that is accessible without passing template parameters first. Is that possible?
namespace foo {
template <typename T>
class bar {
public:
static void eggs();
};
}
foo::bar<some_t>::eggs(); // works
foo::bar::eggs(); // does not work
I would like to avoid moving eggs() to the foo namespace or to create a new namespace for it (eg. foo::bar_::eggs(), ugh).
No. That is not how template classes work. What you want to do is not possible in C++.
Remember that foo::bar does not name any type, but solely a template that can be used to create other types.
Besides using typedefs/type aliases (through using), you can perhaps have a non-templated base class for you templates, and then put your static members there. If you use public inheritance, changing the static member in any of the templated classes will change in all of them.
After experimenting with your code:
I want to add a static function to a template class that is accessible
without passing template parameters first. Is that possible?
namespace foo {
template <typename T>
class bar {
public:
static void eggs();
};
}
foo::bar<some_t>::eggs(); // works
foo::bar::eggs(); // does not work
I would like to avoid moving eggs() to the foo namespace or to create
a new namespace for it (eg. foo::bar_::eggs(), ugh).
I have come to the conclusion that, the first instance of
foo::bar<some_t>::eggs(); // works while
foo::bar::eggs(); // doesn't
Is due to the fact that when working with templates, anything within the class has to be relative to a specific object, even if you do not want the function to be. I even tried using function pointers and tried to save them to template class and without no avail I couldn't even get that to compile. I do not see much of an option for you in this situation. There maybe other tricks out there that someone might know, but not from what I can see.
You can make the template parameter optional and you can define a specialized template. Like this:
namespace foo {
template <typename T = void> class bar {
public:
static void eggs() { cout << "First there was the egg" << endl; }
};
template <> class bar<void> {
public:
static void eggs() {
cout << "Then there was the chicken... or was it?" << endl;
}
};
}
auto main() -> int {
foo::bar<int>::eggs(); // egg
foo::bar<>::eggs(); // chicken
return 0;
}

is it possible to nest to class existing enum

I have enum in some header file. Is it possible to nest to the class existing enum?
Explanation:
some headerfile.h:
enum someEnum
{
someValue
/*other values*/
};
other header:
#include "headerfile.h"
class someClass
{
public:
//using enum someEnum; //don't work as I want
};
I want that someValue will be accesible as
someClass::someValue
So my question is it possible?
You can nest that enum definition:
class someClass {
public:
enum someEnum {
someValue
};
};
Then you can access this enumerations just like the way you wanted:
someClass::someEnum X = someClass::someValue;
If, however, what you wanted was to create a member variable typed someEnum, you can do it either by just supplying someEnum as a type, or nesting the enumeration and putting the variable name before the semicolon.
well one way would be to do this:
class someClass
{
public:
#include "headerfile.h"
//using enum someEnum; //don't work as I want
};
not pretty but works.
You could try to include the library inside the class definition.

template circular dependency issue

second template question of the day, what a n00b:
I have a template class:
template <class T>
class foo{
private:
//...
T SubFoo;
//...
};
I also have a class called myClass. I would like to have objects of the kind:
foo<myClass> myObject;
But, and here's the problem, I would like to be able to get a pointer to myObject from myObject.SubFoo. That means that one of the members of the class myClass should be an instantiation of the template class foo.
So I can do:
class myClass{
//...
foo<myClass>* point2myClass;
}
However, it seems that this does not work because
./foo.h:103: error: ‘foo::SubFoo’ has incomplete type
When defining myClass, the program finds the line
foo<myClass>* point2myClass;
It goes to the defintion of foo and it finds:
T SubFoo;
but T, in this case myClass, has not yet been defined (that is what the program was doing!), so it doesn't know what T is, hence the error.
If I interchange the order of declarations, it will also fail because "foo" will not be defined.
How can I make this work??
Thanks a million!
The following code, should definitely work just fine. If your code is different, please specify where.
template < typename T >
struct A
{
T x;
};
struct X
{
A<X>* x;
};
int main()
{
X a;
}

typedef'ing an enum does not make the enum-values visible

I have a class in which I have an enumeration, defined like this:
class X
{
public:
enum Direction {DIR_LEFT, DIR_RIGHT};
};
Now I want this enumeration to be reused in another class, like this:
class Y
{
public:
typedef X::Direction Direction;
};
As expected, using Y::Direction works correctly, e.g.:
void myFunction (Y::Direction dir)
{
}
But the values within the enumeration does not seem to be 'copied' together with the typedef. If I write the following, I get compilation errors:
myFunction (Y::DIR_LEFT);
Instead, I have to refer to the original place of the enumeration again, like this:
myFunction (X::DIR_LEFT);
Which defeats my purpose of typdefing the enumeration.
The only solution I see is to move the enumeration out of class X, and putting it in another class (e.g. MyEnums), so it can be reused by X and Y (although they should still use MyEnums::DIR_LEFT and MyEnums::DIR_RIGHT), but at least the code does not depend on class X anymore.
Why are the enumeration values itself no exposed via the typedef?
Are there any other patterns to manage enumerations in different classes?
Unfortunately C++ doesn't introduce a new scope with an enum although C++0x is improving things.
Practically this means that you can't typedef an enum and get the enumerated values as well.
What you can do is use a nested struct with the name you want for the enum and typedef THAT.
class X
{
public:
struct Direction { enum EnumType {LEFT, RIGHT}; };
};
class Y
{
public:
typedef X::Direction Direction;
};
Now you can do:
myFunction (Y::Direction::LEFT);
The purpose of the nested struct is to create a "fake" scope to holld both the enum name and its values.
Here is my understanding of how enums work in C++. (Or at least my observed behaviour of enums in Microsoft Visual C++.)
The enum keyword does not create a scope the same way that classes do.
The full name then for your enum 'Direction', is X::Direction. The values within that enum are still part of the class scope, so they are X::DIR_LEFT and X::DIR_RIGHT.
When you typedef the enum in another class, this does not change the scope of the values of the enum.
I suggest you put the enum inside a namespace in a header file if you want to share it in multiple locations.
If you want the enum values to be members of both classes, the
solution is to define a separate class with the enum, and
inherit from it, e.g.:
class MyEnums
{
protected:
~MyEnums() {} // Prevent delete through pointer to this class
public:
enum Direction
{
DIR_LEFT,
DIR_RIGHT
};
};
class X : public MyEnums
{
// ...
};
class Y : public MyEnums
{
// ...
};
Users will see X::Direction, X::DIR_LEFT and Y::Direction,
Y::DIR_LEFT. Of course, they'll still be able to pass
a Y::DIR_LEFT to a function expecting an X::Direction; to
prevent that, make MyEnums a template, with the derived class as
the template argument.
Anything shared by more than one class should be factored outside of the classes and perhaps into a parent class.
direction.hpp:
#ifndef DIRECTION_HPP
enum Direction {DIR_LEFT, DIR_RIGHT};
#endif
x.hpp:
#ifndef X_HPP
#include "direction.hpp"
class X
{
Direction dir;
};
#endif // X_HPP
y.hpp
#ifndef Y_HPP
#include "direction.hpp"
class Y
{
Direction dir;
};
#endif // Y_HPP
If the original declaration:
class X
{
public:
enum Direction {DIR_LEFT, DIR_RIGHT};
};
is embedded in a large legacy code-base, then we might want a solution that does not change any existing uses of X::Direction. In that case, the rather ugly:
class Y
{
public:
typedef enum X::Direction Direction;
static const enum X::Direction DIR_LEFT = X:DIR_LEFT;
static const enum X::Direction DIR_RIGHT = X:DIR_RIGHT;
}
works...
Definitely not recommended for new code, however!