Say you have a class template (e.g. second below). Say that class template's template arguments are instantiations of another class template (e.g. first below). How do you access the template argument's own template arguments? Is that possible?
Here's some code:
template<size_t n>
class first {
};
template<typename instantiated_first>
class second {
// would like to be able to access the "n"
// of instantiated_first
};
int main() {
second<first<3>> thing;
return 0;
}
Three possibilities come to mind:
rewrite first to store n as a data member, or
redesign second to inherit from an instantiated class from first, and
ask for the exact same template arguments in both class templates.
I ask because I would rather not edit pre-existing code (option 1), and in my particular application, it doesn't really make sense (to me, at least) to think of second as being a type of first (option 2). I will be instantiating many objects of type specialized_first, and so it makes more sense for second to "own" these objects and store them in a container. Option 3 doesn't seem very stylish, either.
Are there any fancy template features that I don't know about to accomplish this in a nice way?
The more sensible way is not to store n as a data member but rather as static constexpr size_t so it doesn't allocate any additional runtime space. This is the standard and most flexible mechanism - allowing for various other templates to access this parameter without mush fuss. E.g., you can make a completely different version of first and allow your second to utilize the other version all the while supporting the original as long as all version satisfy the concept interface.
Similarly, every typename T_ template parameter can be forwarded to users of the template via using T = T_;. In general, template parameters are inaccessible unless you allow them to be by declaring them to be types or storing their value as constexpr or otherwise.
You can remodel second so it accepts the same template parameter but it becomes harder the more other templates you have that use first and this value/type or when you suddenly want to use second for an alternative version of first. Better address such problems on the root. For example, in std all their template classes have all the necessary types declared inside the class in a similar manner.
You declare a partial specialization and pick the arguments from there.
template<typename T>
class second<first<T>> {
// T is available here for use.
};
Or even more generally do this
template<typename T, typename U
class second<U<T>> {
// T is available here for use.
};
This will match all instantiations with one template argument.
Related
I want to instantiate a template from the STL, using maps,vectors, and arrays, as follows:
map<some_type,vector<map<some_type,vector...>*>> elements;
The ellipses is just pseudo-code to represent the infinitely recursive definition, which is ofcourse impossible to type out. Basically, the vector should just hold pointers to other maps that are identical in structure/definition to the map in which the vector is contained. I know there are workarounds using classes and structs, the question is whether it is possible using only templates. I was hoping I could somehow define the whole outer map as some kind of "template-variable" or other place-holder such as "T", then write the following:
map<some_type,vector<T*>> elements;
where I would separately define T as referring to the whole map. But due to recursion, such a variable T would be defined in terms of itself, ie sub-components that are themselves T. Later I would then at runtime as necessary allocate more maps on the heap and insert pointers to them in the vector, such that I can then recursively (indefinately often), traverse into the map within the vector, just so that I can then instantiate more maps on the heap, again holding pointers to them within the vector.
Is there an (elegant) way to do this (if at all)?
You were on the right track by abstracting out the recursion variable:
template <typename Self>
using F = std::map<int, std::vector<Self*>>;
The problem is to find a type T such that T == F<T>. This is known as finding the fixed point. In these terms, we want a template Fix taking a template template parameter such that Fix<F> == F<Fix<F>>.
Abstractly, in a lazy functional language, Fix<F> = F<Fix<F>> could serve as a definition of Fix<F>. This coincidentally tells us exactly what breaks down in C++. In C++ notation this hypothetical definition would look like:
template <template<typename> typename F>
using Fix = F<Fix<F>>; // does not compile
This depends fundamentally on laziness, but templates are lazy by nature so that isn't a problem. The real problem is name lookup. We cannot refer to Fix on the right-hand side in C++. That's a somewhat artificial restriction, but that's the language we have.
I cannot see a way around that, so I cannot avoid introducing one generic helper struct:
template <template<typename> typename F>
struct Fix : F<Fix<F>> { };
Although aliases cannot reference their own name in the definition, classes and structs can.
With all of that out of the way, we have our solution:
// Our type
using Type = Fix<F>;
// It instantiates
auto map = Type{};
// The inner type is the same as the outer type
using inner_type = std::decay_t<decltype(*std::declval<Type::mapped_type::value_type>())>;
static_assert(std::is_same_v<Type, inner_type>);
// We can push_back the address of ourself
map[0].push_back(&map);
See this on godbolt.
I'm reading Scott Meyers C++ and came across with the concept of so-called code bloat. He provided an example of how to reduce it with inheritance:
template <typename T>
class SquareMatrixBase{
protected:
void invert(std::size_t matrixSize); // <------------ HERE
}
template <typename T, std::size_t n>
class SquareMatrix : private SquareMatrixBase<T>{
private:
using SquareMatrix<T>::invert;
public:
void invert(){ invert(n) }
}
Now, in the summary of the item he stated that
Templates generate multiple classes and multiple functions, so any
template code not dependent on a template parameter causes bloat.
So, in the example we have SquareMatrixBase<T>::invert(std::size_t) which is not dependent on the template parameter. So, it causes code bloat. Isn't that the thing we tried to eliminate? What did I miss?
So, in the example we have SquareMatrixBase<T>::invert(std::size_t) which is not dependent on the template parameter. So, it causes code bloat. Isn't that the thing we tried to eliminate? What did I miss?
No. You missed that the operations invert performs on the matrix will be dependent on T, so it's appropriate to have one instantiation of invert for each T.
It is not desirable to have one instantiation for every combination of type T and matrix size n, which is why the derived SquareMatrix class - that is templated on both those parameters - defers to the base class' implementation. It's effectively just injecting the matrix size constant as a runtime value.
As the SquareMatrix template is parameterized on two things T and n, then even though you might have the same type T, if you were to have a different n and invert was a member function of SquareMatrix, it results in multiple versions of the function (a number depending on how many SquareMatrix's of the same T but different sizes we instantiate).
Scott is demonstrating how we can avoid the potential bloat caused by these multiple copies, by simply inheriting from a type that is only parameterized on T and so can share an implementation of invert regardless of the value of n.
He passes the size value at runtime to the base class function and so all the same information is available to that function.
I have stumbled many times on classes defined like
class PureVirtualClass
{
virtual int foo() = 0;
virtual bool bar() = 0;
}
template <class T> class ImplClass : public virtual PureVirtualClass
{
virtual ~ImplClass(){};
int foo() { return 42;}
bool bar() { return true;}
//several other method having nothing to do with T
}
This "design" appears so often I want to think the original developer knew what he was doing by defining ImplClass as template class but without any reference to the template argument T anywhere. My own c++ template knowledge is kinda limited.
Is there a benefit to this or is it just a confused programmer?
There can be a benefit for classes being templated but not depending on the argument. Most often you see such things to define (empty) tag-structures for template metaprogramming:
template <class X>
struct some_tag {};
The benefit of classes like yours in general is that while you have the same functionality in each class, they are different classes and you can't copy one into the other, i.e. an object of type ImplClass<int> is not compatible with another object of type ImplCalss<float>.
There are many useful cases of the idea mentioned by Arne. For instance, looking at Very basic tuple implementation, this is how a single tuple element is defined:
template <size_t N, typename T>
class TupleElem
{
T elem;
public:
T& get() { return elem; }
const T& get() const { return elem; }
};
It is templated on N, without depending on it. Why? Because the tuple implementation
template <size_t... N, typename... T>
class TupleImpl <sizes <N...>, T...> : TupleElem <N, T>...
{
//..
};
derives multiple such elements, each with a unique N, serving as an identifier. Without it, TupleImpl would be deriving the same class twice, had two element types been identical within parameter pack T.... Neither random access to elements would work in this case (via an explicit call of function get() of the appropriate TupleElem base class, which would be ambiguous), nor empty base optimization (via specializing TupleElem for empty types T to not have a data member of type T).
This is a real use case, and exactly how std::tuple is implemented by clang. Of course, a class like TupleElem would be a hidden implementation detail, and not part of the interface. For instance, gcc follows an entirely different recursive class design.
In general, you will need to study the context where classes are used to understand the intent of the designer.
maybe that developer simply is too lazy to split the classes into .h and .cpp files?
Without using templates, linker errors would occur if the classes are used in multiple compilations units. When using templates, the linker usually discards duplicate instantiations of a template at link time (or handles the problem in a different way).
While this may be an answer to "why did the developer do this", I would not recommend this if the question was "when should I introduce template arguments which are never used" (see the other answers for this). Even though it is annoying to split code into .h and .cpp (especially when used to languages like Java or C#), it's the usual C++ way. And it is definitely easier to read/understand than using templates only for this purpose. Also, it makes the use of the classes less readable.
I wish to modify an existing templated class. The class's template arguments are (semi) variable and I would like to use them to generate a conditional/switch/map like function body.
My compiler does not support variadic templates so the (boost) preprocessor is currently used to generate the existing class:
template <typename item0, typename item1, typename item2 ..., typename itemN>
struct myclass { /*various operations*/ };
A new function func is required that will query variables at run-time and return an object of a that is one of the template arguments.
Example:
template <typename item0, typename item1, typename item2 ...>
struct my_class {
//...various operations
//automatic generatation possible?
std::string * func()
{
string s;
while(data) {
switch (data[0])
{
case item0::id:
s += item0::get_name();
case item1::id:
s += item1::get_name();
//... for each template arguemnt typename where typename is no void
}
}
return s;
}
};
typedef my_class<a, b, c> class_one;
typedef my_class<d, e, f> class_two;
typedef my_class<a, b, c, x, y, z> class_three;
int main()
{
...
class_one test;
test.func();
...
}
I would like to generate the contents of func() because the number of items will be numerous, and the number of types of "myclass" will be even higher.
Can someone give me an idea of how any techniques that could accomplished this?
I already have a dependency on boost. My compiler is reasonably new (but does not support variadic templates). I would prefer not to take any new dependencies or introduce more complexity than necesssary.
I've written code like this before, so I can tell you it is possible. (It was for commercial, closed-source work, so I'm afraid I can't show you the code). You can find a really good example of how to do this in the Boost.Variant library, in particular http://svn.boost.org/svn/boost/trunk/boost/variant/detail/visitation_impl.hpp . The code is very dense and advanced C++, so it might take a day or two to understand it thoroughly.
A quick summary: the boost::variant class template works like a union with an int storing which member of the union is valid. The "visitation" feature lets you supply a function object with an overloaded operator() that can take any of the possible members of the union, and it generates a switch statement that accesses the appropriate member and calls the right operator() overload on it. If you are already finding this complicated to follow, or you don't know about Boost.MPL yet, I suggest you stop reading here, read the Boost.Variant documentation, and then rewrite your class to be able to use that: the clever guys at Boost have already done the work for you. It's header-only, so if you're already using Boost there's no new dependency for you.
This file is in charge of generating the switch statement. In short, it has two alternative implementations. The first one (lines 72-90) uses a recursive template visitation_impl_step that works like the factorial function you might have seen as a template meta-programming example. The unspecialized template recursively calls the next one in the list (typename mpl::next<Iter>::type). The resulting code, once all the templates are expanded out, looks a bit like a series of functions function0, function1, &c. like this:
result_type functionN(variant vnt, visitor vr) {
if (v.which == N)
return vr(static_cast<Nth type>(vnt.value));
else
functionN-1(vnt, vr);
}
The second implementation (lines 193-285) uses the Boost.PP preprocessor magic library to generate a switch statement just like the one you want, with as many cases as a boost::variant can possibly have. The body of each case is a call to a template function (lines 120-185) which generates a call to the visitor on the Nth type. Most of the complexity in this implementation comes from having to worry about backing up the value inside the variant in order to preserve the strong exception guarantee if the visitor or any involved constructor throws.
Even if you decide to do it another way, I recommend reading and understanding the Boost.Variant source code, as a learning exercise. It will redefine your ideas of what is possible (and what is sensible) in C++!
Compiler will be able to generate code using exact template definition. There is no way to force compiler to generate additional cases in switch statement or additional iterations of loops depending on template parameters.
If you want to perform perform some action on instance of each type specified in template parameters you have to implement recursive template function. Please refer to this question for details.
I have a dilemma. Suppose I have a template class:
template <typename ValueT>
class Array
{
public:
typedef ValueT ValueType;
ValueType& GetValue()
{
...
}
};
Now I want to define a function that receives a reference to the class and calls the function GetValue(). I usually consider the following two ways:
Method 1:
template <typename ValueType>
void DoGetValue(Array<ValueType>& arr)
{
ValueType value = arr.GetValue();
...
}
Method 2:
template <typename ArrayType>
void DoGetValue(ArrayType& arr)
{
typename ArrayType::ValueType value = arr.GetValue();
...
}
There is almost no difference between the two methods. Even calling both functions will look exactly the same:
int main()
{
Array<int> arr;
DoGetValue(arr);
}
Now, which of the two is the best? I can think of some cons and pros:
Method 1 pros:
The parameter is a real class not a template, so it is easier for the user to understand the interface - it is very explicit that the parameter has to be Array. In method 2 you can guess it only from the name. We use ValueType in the function so it is more clear this way than when it is hidden inside Array and must be accessed using the scope operator.
In addition the typename keyword might be confusing for many non template savvy programmers.
Method 2 pros:
This function is more "true" to its purpose. When I think if it, I don't really need the class to be Array. What I really need is a class that has a method GetValue and a type ValueType. That's all. That is, this method is more generic.
This method is also less dependent on the changes in Array class. What if the template parameters of Array are changed? Why should it affect DoGetValue? It doesn't really care how Array is defined.
Evey time I have this situation I'm not sure what to choose. What is your choice?
The second one is better. In your "pros" for the first one, you say, "it is very explicit that the parameter has to be Array". But saying that the parameter has to be an Array is an unnecessary limitation. In the second example, any class with a suitable GetValue function will do. Since it's an unnecessary limitation, it's better to remove it (second one) than to make it explicit (first one). You'll write more flexible templates, which is useful in future when you want to get a value from something that isn't an Array.
If your function is very specific to ArrayType, and no other template will satisfy its interface requirements, use #1 as it's both shorter and more specific: the casual reader is informed that it operates on an ArrayType.
If there's a possibility that other templates will be compatible with DoGetValue, use #2 as it's more generic.
But no use obsessing, since it's easy enough to convert between them.
My friend proposed two more, somewhat more extreme, methods:
Method 3: gives you the ability of using types that don't have a ::ValueType.
template <typename ArrayType, typename ValueType = ArrayType::ValueType>
void DoGetValue(ArrayType& arr)
{
ValueType value = arr.GetValue();
...
}
Method 4: a cool way of forcing the array to be a class that has one template parameter.
template <template <typename> class ArrayType, typename ValueType>
void DoGetValue(ArrayType<ValueType>& arr)
{
ValueType value = arr.GetValue();
...
}