I'd like to define two variations of a class depending on a template parameter in a C++ class. (I'm using C++17.)
For example, if the template parameter bool flag is true, I'd like the class to have a member:
Class1 foo;
and if flag if false
Class2 bar;
The class definition would also have some logic variation and use either foo or bar. I could implement this using inheritance but I'm exploring if there's another approach. It seems that https://en.cppreference.com/w/cpp/types/conditional may be helpful but I'm not sure. I could also just have both members and just use one of them in any given object, but that seems wasteful and there must be a better way. Note that I don't necessarily need to name the members differently if a particular solution would simply allow me to swap out the class but not the name (perhaps with conditional?).
If you can live with the same member name for both versions, then it is trivial:
template <bool flag>
struct Foo {
std::conditional_t<flag, Class1, Class2> foo;
};
Related
Is there any interest to forward a class as a struct and vice versa ?
It seems to be perfectly legal, but some use cases exist ?
struct Bar;
class Foo
{
Bar * bar_;
};
class Bar
{
};
There isn't a use case any more or less than there is a use case for forward declaring with the same keyword. It makes no difference to the meaning of the program. The class-key identifier only makes a difference when defining the class.
The above applies to standard compliant compilers. Some non compliant ones might handle the declarations differently in which case there is a case for using the same keyword in particular.
Ok, here is a practical use case. Let's say you've implemented a class with the struct keyword. Over time, the class is widely used across multiple code bases and it is declared in many headers using the same keyword. At a later time, perhaps after adding a ton of features, you decide that classwould be more appropriate and you refactor the code. Now, there isn't a point in refactoring all the unrelated depending code bases to use the new keyword.
struct Bar;
class Bar;
These are equivalent, it doesn't matter.
but some use cases exist ?
No special ones IIRC.
From the language's point of view, there is no difference between forward-declaring a class as struct or class.
class Foo;
struct Foo;
class Bar;
struct Bar;
class Foo{}; // 100% ok
struct Bar{}; // 100% ok
Unfortunately, some compilers mangle those keywords differently. As described here, this can be nasty when you're depending on name mangling being the same.
Consider:
// process.h
struct Foo;
void processIfNotNull(Foo*);
// foo.h
class Foo{};
If you export such function in your shared library, your users will not be able to call processIfNotNull unless they have the definition of Foo.
It's not usefull.
In C++ the difference between struct and class is that for struct members are public by default.
Considering this, in your example it could just confuse the code reader to determine if your class will behavior as a struct or a class.
You can read this post for further information : When should you use a class vs a struct in C++?
Is there a good rule when to use a class template instead of using member templates?
As I understand it, your are forced to use a class template if your class contains member variable templates but otherwise you are free of choice since this:
template<typename T>
class Foo
{
public:
void someMethod(T x);
};
behaves like this:
class Foo
{
public:
template<typename T>
void someMethod(T x);
};
Is my claim wrong? Or is there any rule of thumb when to use what?
The two are not at all the same. With the first:
Foo<int> f;
f.someMethod('a');
the called function is someMethod(int).
With the second:
Foo f;
f.someMethod('a');
the called function is someMethod(char).
You can choose to make your class a template, rather than having member function templates, for several reasons. Say you have a template parameter T.
Like you said, if you have a member variable of type T, your class needs to be a template.
If you have a function returning T and not accepting T, and you don't want to manually specify the type in each invocation, your class needs to be a template.
If you need a virtual function that depends on T, your class needs to be a template.
If you need a different class layout (i.e. member variables) per instantiation of T, your class needs to be a template.
If you need to make sure that your functions all operate on a single type rather than generate different versions of them arbitrarily, your class needs to be a template.
The best rule of thumb would be to use the simplest thing that makes sense. In general, member function templates tend to be more rareāand virtually non-existent for the use case you're talking about. Maybe that's no coincidence.
The following code doesn't compile because the compiler doesn't know what foo::bar is when it encounters it.
class foo : foo::bar {
class bar {
}
}
Is there any way to make this code (or some variation of it) compile?
If the inheritance from bar is an implementation detail and the goal is to avoid polluting the global namespace (or the library's namespace), a common approach is to put these implementation details in a namespace named detail. This is a convention used in libraries like Boost, for example.
namespace super_cool_library {
namespace detail {
class bar { };
}
class foo : detail::bar {
};
}
The detail namespace is, admittedly, just a convention, but most people understand that within said namespace there be dragons.
Edits:
As Emilio Garavaglia suggests, foo would need to befriend detail::bar if detail::bar should need to have the same access to foo that a C++11 inner class would have.
I don't know why, but I find this question very interesting. Especially seeing how many answer try not to give a technical reason why the language don't allow this, but try to convince the author about the "ugliness" of such a definition (tha's ultimately a subjective matter).
Although the form of the question looks unconventional, what is asking is perfectly linear: since recursion is one of the primitives behind certain programming paradigms (that C++ claim to support, like the functional paradigm), if functions are allowed to be recursive (either directly or indirectly) why the same cannot apply to data definitions?
After all, if what is asked is possible a universe of interesting features opens in the area of meta-programming: when a generic traits class is used as a type generator for a generic class defining generic algorithms on top of a generic state, having a constructor like that can allow (among other things) to place the type generator into the generic class itself, simplifying the overall parametrization, leading to a completly different way to approach the generic algorithms and their "progressive partial specialization".
The rereason why this is not possible, is that C++ compilers, have to support independent translation units (that links after compilation), and have to support a non-orthogonal grammar (this is know as the "undecidable syntax problem").
Because of those two facts together, C++ cannot have a pure recursive global parser. You cannot use "unknown symbols" letting the association of that symbol to something concrete to happen later because the way to interpret the expression that symbol appears in, depends on the nature of that symbol itself: a<b>c is declaration of a variable, or an expression involving variables? You cannot know if you don't know if a and b are variables or types.
And since the "nature of a symbol" is "compiler internal state", you cannot use foo::bar as it is a class (like as a base to form a derived one) before knowing it really IS a class (and not a variable or something else). But this happens only later (when the class bar declaration is met).
This is the same reason that lead to have forward declarations, and declaration separated from definitions: a(b) cannot be transalted if at least a is not known to be a "callable object". If a is function, at least its prototype must be known when a(b) is met.
But in your case there is no way to anticipate the foo::bar declaration being the bar declaration to stay inside the foo definition.
To come to a solution the language should support someting like
1: class foo; //we know foo is a class
2: class foo::bar; // we know bar is a class inside foo scope
3: class foo::bar
{
...
}; //we know here how wide foo::bar is
4: class foo: public foo::bar // we must know about foo::bar width here...
{
...
}; //... to sum up the foo size.
The problem, here, is that 2: is not legal C++: the compiler has not yet seen the bar symbol alone, with the word class before it.
But this requires
class foo
{
class bar;
};
to already exist. But if you make that to exist you cannot anymore declare class foo: public bar {...}; later.
In other words, you meet an non-orthogonality in the grammar. The point is that it will not be solved, since around this inconsistency there have been deployed a number of programming paradigms that does not require that construct to work, and have already make enough brainwashing to let sooo many people (just look at the comments in you question and under the most of the answers) the let them to just refuse the idea even before trying to understand if it can be useful to something. They just say "I don't like that something, since I just have something else to like, and that can disturb me. And try to find false metaphors to support motivations that -ultimately- reside in the old C compilation model C++ still has to deal with.
It's not possible to have the outer class inherit from a nested class. It also doesn't make that much sense if you think about it. A class derives from its internal subclass? That's like a snake eating its own tail.
More likely you want both to share common methods. In this case you can create another class which provides a common interface/base for foo and foo::bar.
class common_base{ /* ... "shared" content ... */ };
class foo : public common_base{
class bar : public common_base {
/* depending on what you want to do this can be empty */
}
}
you can however do this:
struct A
{
struct B
{
};
};
struct C : public A::B
{
};
I don't think C++ supports what you want, but if the goal is to avoid polluting the global namespace with "bar", how about putting bar into a separate namespace? E.g.
namespace shums_private_namespace {
class bar {
};
};
class foo : shums_private_namespace::bar {
public:
foo() {/* empty */}
};
I have no idea why you'd want to do this, but if it's tricks you're looking for, CRTP-like things are always fun:
template <typename T>
struct Foo : public T
{
struct Bar
{
};
};
struct empty {};
int main()
{
typedef Foo<empty>::Bar Bar;
Foo<Bar> f;
}
Is this answer considered "good" code or is it just an ugly hack?
And I would like to know how this is forward-declared (both classes).
When I just forward-declare the class with 2 template-parameters, it just always takes this one, no matter what value flag has.
I would like to do this because I have 2 special member functions which should behave differently on flag being true and I don't feel like reimplementing the whole class. Also, it should have the same name. According to this example, this seems to be possible.
And I have to forward-declare it because I'm creating a library in which we forward-declare everything.
Any idea?
It has the drawback that it doesn't really work. The base member function is not overridden, but it is just hidden by the derived class' function when you try to call it from outside. Which means if you call doSomething out of the base class (where presumably all your other functions live) it will call the base class doSomething which is not what is wanted.
The accepted answer on that question shows multiple ways for how you can solve your problem.
In order to use specialisation its definition always has to be visible to the caller. If, for example, you have template <class Type, bool flag> struct something defined in one header and template <class Type> struct something<Type, true> : public something<Type, false> defined in the second one, to use the latter you have to include the second header. Without that you will always get the first, more generic type.
EDIT: the bit about forward-declaring got me thinking. If you want to use only type declaration, as in pointer variable, do the following:
Header
template <class Type, bool flag>
struct something;
struct Test
{
something<int, true>* ptr; // definition not needed
Test();
}
Source
#include "something.h" // header with template
#include "something_spec.h" // header with specialisation
Test::Test()
{
ptr = new something<int, true>(); // specialisation used
}
I never really had a necessity for a global variable in a template (and actually I don't support a design like this very much) but this topic got me curious.
Even though answered, it inspired me trying a different approach. Instead of using inheritance, I came up with this:
class Bar {};
class {
private:
Bar bar;
template <class T> friend class Foo;
} static foobar_singleton;
template <class T>
class Foo
{
public:
static Bar bar() { return foobar_singleton.bar; }
};
To me, the foobar_singleton works similarly to a 'non-member static private', since its content will be only acessible by the template class Foo. It also avoids inheritance though I am not sure this is an advantadge actually. My solution seems possible to be contained header-only, without necessity about another definition file.
I would like to see what are the opinions about this approach compared to the one utilized as an answer for the thread that got me curious. For instance, some examples of questions I'd like to hear about:
1. Do you see any clear advantadge in my example? Or for that matter, clear disavantadge?
2. Would you advice making bar attribute a static member and naming the class used as singleton?
3. This reminds any of you of any design pattern? Similar to pimpl idiom maybe?
4. You see any compiler portability problems? (I've tested it only with MSVC and GCC)
5. I'm right about being a possible header-only implementation? I'm actually not completely sure about the static variable foobar_singleton
Thanks in advance!
The static variable foobar_singleton in your example will be a different variable in every translation unit (internal linkage!). Which is a kind-of a show stopper.
The inheritance in the original topic is only used to "inject" the common static variable into the namespace of the template. If that's not a requirement, just don't derive Foo from FooBase, works just as well.
If it's needed for whatever reason, I would derive privately, which should eliminate any possible side effects one could encounter from introducing an additional base-class. And of course add the helper-class as the last base-class, if Foo inherits other classes too.
If you want a header-only solution:
typedef int Bar;
template <class DummyType>
class FooCommonStatics
{
static Bar s_bar;
template <class T>
friend class Foo;
};
template <class DummyType>
Bar FooCommonStatics<DummyType>::s_bar;
template <class T>
class Foo
{
public:
// void is just a dummy-type, any type that's not dependent on T would do
typedef FooCommonStatics<void> CommonStatics;
Foo()
{
CommonStatics::s_bar++;
}
private:
T m_something;
};