c++11 variadic template class not compiled - c++11

template <template <class ...args1> class T1, template <class ...args2> class T2>
class CollisionManager
{
public:
CollisionManager(void);
~CollisionManager(void);
bool checkCollision(T1<args1...> firstArray, T2<args2...> secondArray);
};
For some reasons compliler alerts args1 and args2 in checkCollision() as undeclared identifier

args1 and args2 are just placeholders. You can just omit them. Also notice that the parameters to your class template are also templates, not types. When CollisionManager gets instantiated args1 and args2 are not even bound to any types.
Update:
It seems to me, that you want to write something like this:
template <class T1, class T2> class CollisionManager;
template <template <class...> class T1,
template <class...> class T2,
class... args1,
class... args2>
class CollisionManager<T1<args1...>, T2<args2...>>
{
public:
CollisionManagerImpl(void);
~CollisionManagerImpl(void);
bool checkCollision(T1<args1...> firstArray, T2<args2...> secondArray);
};

Related

Aliasing a template template parameters

Is it possible to use the using keyword for aliasing a template template parameter?
template <template<int> class T>
struct Foo {
using type = T;
};
Thanks
using (or typedef) always provide an alias for a type, never for an higher-kinded type (template template parameter). What you can do is templatize the alias itself on the int:
template <template<int> class T>
struct Foo {
template <int X>
using type = T<X>;
};

Out-of-line member template function definition using another member template function in the signature

I ran into this problem in some real-life C++11 code, but I boiled it down to this:
template<int i> struct Dummy {};
template<typename T>
struct Foo {
template<int i> static constexpr int bar() { return i; }
template<int i>
static auto working() -> Dummy<bar<i>()>;
template<int i>
static auto also_working() -> Dummy<Foo<T>::template bar<i>()>;
template<int i>
static Dummy<Foo<T>::template bar<i>()> not_working();
};
template<typename T> template<int i>
auto Foo<T>::working() -> Dummy<bar<i>()> {
return Dummy<bar<i>()>{};
}
template<typename T> template<int i>
auto Foo<T>::also_working() -> Dummy<Foo<T>::template bar<i>()> {
return Dummy<bar<i>()>{};
}
template<typename T> template<int i>
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
return Dummy<bar<i>()>{};
}
I was trying to create an out-of-line definition of a template member function of a template class, where the signature of the function involved calling another template member function and started out with something like the not_working() function. The problem was that the definition failed to match the declaration.
Clang said:
clang++ -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -std=c++11 -c -o out_of_line.o out_of_line.cc
out_of_line.cc:28:42: error: out-of-line definition of 'not_working' does not match any declaration in 'Foo<T>'
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
^~~~~~~~~~~
GCC said:
g++ -Wall -Wextra -pedantic -std=c++11 -c -o out_of_line.o out_of_line.cc
out_of_line.cc:28:34: error: prototype for ‘Dummy<bar<i>()> Foo<T>::not_working()’ does not match any in class ‘Foo<T>’
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
^~~~~~
out_of_line.cc:14:43: error: candidate is: template<class T> template<int i> static Dummy<Foo<T>::bar<i>()> Foo<T>::not_working()
static Dummy<Foo<T>::template bar<i>()> not_working();
^~~~~~~~~~~
By trial and error I discovered that using a trailing return type I could get the definition to match the declaration, yielding the also_working() function. Once there I realized that due to the change of scope in the trailing return type I could do away with some name qualification, yielding the much prettier working() function.
Now I wonder why the not_working() function is not working, i.e. why its definition does not match its declaration (I could just settle in ignorance with the solution I found, but I'm likely to encounter more of this kind of issues and I don't want to waste more time using trial and error); does the bug lie within the compilers or within my code. I've read through 14.6 Name resolution [temp.res] but I'm not sure what rules are applicable for this case.
Clarification of the question: Given the rules in the C++11 standard:
should the not_working() definition match the declaration?
which rules are involved in determining 1.?
how do the rules from 2. interact when determining 1.?
It looks like it's trying to implement CWG2 but is possibly doing things in a surprising order. Looking at gcc's errors:
prog.cc:28:34: error: prototype for 'Dummy<bar<i>()> Foo<T>::not_working()' does not match any in class 'Foo<T>'
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
^~~~~~
prog.cc:14:43: error: candidate is: template<class T> template<int i> static Dummy<Foo<T>::bar<i>()> Foo<T>::not_working()
static Dummy<Foo<T>::template bar<i>()> not_working();
^~~~~~~~~~~
The definition is seen with the return type Dummy<bar<i>()> but the candidate declaration has return type Dummy<Foo<T>::bar<i>()>. Specifically, the Foo<T>:: qualification on bar<i> has been lost.
Changing the definition of also_working to have return type Dummy<Foo<T>::template bar<2>()>, we get useful parallel errors:
prog.cc:23:6: error: prototype for 'Dummy<Foo<T>::bar<2>()> Foo<T>::also_working()' does not match any in class 'Foo<T>'
auto Foo<T>::also_working() -> Dummy<Foo<T>::template bar<2>()> {
^~~~~~
prog.cc:11:15: error: candidate is: template<class T> template<int i> static Dummy<Foo<T>::bar<i>()> Foo<T>::also_working()
static auto also_working() -> Dummy<Foo<T>::template bar<i>()>;
^~~~~~~~~~~~
Here the definition is seen with the return type Dummy<Foo<T>::bar<2>()> (as written), and the candidate declaration has return type Dummy<Foo<T>::bar<i>()>.
Clearly, Foo<T>::bar<i> is different from bar<i> even in the context of Foo<T>, since removing Foo<T>::template out of either the declaration or definition of the return type of also_working makes it stop working. (Taking both out gets you back working.)
I tried changing the declaration of not_working to be:
template<int i>
static Dummy<bar<i>()> not_working();
and now gcc complains:
prog.cc:28:34: error: prototype for 'Dummy<bar<i>()> Foo<T>::not_working()' does not match any in class 'Foo<T>'
Dummy<Foo<T>::template bar<i>()> Foo<T>::not_working() {
^~~~~~
prog.cc:14:26: error: candidate is: template<class T> template<int i> static Dummy<bar<i>()> Foo<T>::not_working()
static Dummy<bar<i>()> not_working();
^~~~~~~~~~~
Which is pretty clearly nonsensical, since we have character-for-character-comparable declaration and definition Dummy<bar<i>()> Foo<T>::not_working(), once the compiler's done with it.

C++: template class inheritance with variable-type parameters using parameter packs

(I had no idea how to name this question and I couldn't find anything similar. Sorry if this is duplicate)
If I want to inherit from some base template class, I can do this that way:
template<typename A=int, typename B=char> class C {};
template<typename... Args> class D : public C<Args...> {}; //it works!
This way I can change in project passed parameters to template class C and I don't have to change every usage of class D. Great. But what if I have template class using not only types as parameters but also values? For example:
template<int dim=3, typename float_t=double> class GeometricObject{};
template<typename... Args> class Point : public GeometricObject<Args...>{}; //it doesnt work
Of course I could define last template with integer type on the beginning. But this is not a way, if I would have 100 different classes all inheriting from GeometricObject and then I would change default dim value to 2, I would have to change every single class definition.
I also hope that there is the way without using any #define, #else and similar preprocessor commands. I know that templates are in fact also preprocessor commands, but... well, let's be modern here ;)
You can not mix type and non-type parameters in a template parameter pack. But it seems that your Point and other derived classes don't need to access the parameter pack arguments separately. In such cases it's easier, as well as more semantically correct, to pass the base class:
template<int dim=3, typename float_t=double> class GeometricObject{};
template<class GeometricObject=GeometricObject<>> class Point : public GeometricObject{};
Instantiating a Point could then look like:
Point<> a{}; // the same as Point<GeometricObject<>> a{};
Point<GeometricObject<4>> b{};
Point<GeometricObject<2, float>> c{};
Of course the GeometricObject<...> could be typedef'd to something shorter. Also, it can be made to look like a namespace instead of providing parameters to each geometric object separately:
template<int dim = 3, typename float_t = double>
struct GeometricObjects {
using Base = GeometricObject<dim, float_t>;
using Point = ::Point<Base>;
// ...
};
using TwoDim = GeometricObjects<2>;
TwoDim::Point a{};
I suppose you have multiple template classes and you want your Point object to be able to inherit from them all.
Instead of doing:
template <typename ... Args>
class Point : public GeometricObject<Args...>{};
I would instead do:
template <typename T>
class Point : public T {};
Now we just have to define proper traits to access the types template parameters in case they are needed. These types should be factored into a std::tuple (for instance).
The burden to fill this trait is on the GeometricObject class. For example, with your definition we would have:
template <typename T>
struct type_parameters;
template <int N, typename Float>
struct type_parameters<GeometricObject<N, Float> {
typedef std::tuple<Float> types;
};
The main scenario: a method of Point needs the type template parameters of GeometricObject (to forward them to a method of GeometricObject). To achieve this, you will have to pass in a tuple that will be unfold to call the inner method. To do so I make use of features added in the STL for C++14. You could still rewrite them yourself but I spared me the hassle for this question...
template <typename T>
class Point : public T {
template <typename Method, typename ... Args, std::size_t ... Is>
auto call_unfold(Method method, std::tuple<Args...> const& tuple, std::integer_sequence<std::size_t, Is...>) {
return (this->*method)(std::get<Is>(tuple)...);
}
template <typename Method, typename Tuple>
auto call_unfold(Method method, Tuple const& tuple) {
return call_unfold(method, tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
public:
typedef typename type_parameters<T>::types types;
void some_method(types const& args) {
return call_unfold(&T::some_method, args);
}
};
This example is quite meaningless but the same technique could be useful with constructors of Point that need to call a base class constructor.
A live demo showing how it works is available on Coliru
Ok, so I figured it out how I should include variable-type template parameters into tuples. Basically I need to 'encapsulate' them into new parameter. This example works perfectly well AND solves my problem:
#include <type_traits>
template<int n = 2> struct Dim {
const int dim = n;
};
template<typename T> class SillyBaseClass {
public:
typedef typename T dim;
};
template<typename... Args> class SillyDerivedClass : public SillyBaseClass<Args...>{
public:
typedef typename SillyBaseClass::dim dim;
SillyDerivedClass() {
static_assert(std::is_same<dim,Dim<2>>::value,
"Number of dimensions must be equal to 2");
}
};
int main() {
SillyDerivedClass<Dim<2>> Class2d; //this works
SillyDerivedClass<Dim<3>> Class3d; //this returns expected error
}

Check if two variadic derived classes are instantiated with the same parameter pack

In situations, when you have a base and many derived classes, all of which encode a variadic pack, something like the following
template<typename ... Args>
struct base
{};
template<typename ... Args>
struct derived_1: base <Args...>
{};
template<typename ... Args>
struct derived_2: base <Args...>
{};
How does one check if objects of different derived classes were instantiated using the same pack. For instance given
derived_1<int,float,double> d1_obj;
derived_2<int,float,double> d2_obj;
I want a mechanism to tell me that both objects are equal, in the sense that they contain the same types in the same order.
You can do this using template template parameters and partial specialization for when arguments match:
template <class T, class U>
struct same_args : std::false_type{};
template <template <typename...> class T, template <typename...> class U,
typename... Ts>
struct same_args<T<Ts...>, U<Ts...>> : std::true_type{};
Then same_args<derived_1<int,float>, derived_2<int,float>>::value will be true.
Live Demo

Compilation failure when using a base class reference as a predicate

class baseFunctor{
virtual ~baseFunctor() {}
virtual bool operator()(const A& lhs, const A& rhs) = 0;
};
class derivedFunctor : public baseFunctor{
bool operator()(const A& lhs, const A& rhs) override { /*implementation*/ }
};
Inside another unrelated method, I have :
baseFunctor* functor = new derivedFunctor();
std::vector<A> vectorA;
My intention is to use this functor as a compare function like this:
std::make_heap(vectorA.begin(),vectorA.end(),*functor);
However, I get the following error:
C2893 Failed to specialize function template 'void
std::make_heap(_RanIt,_RanIt,_Pr)'
What is the proper way to use my pointer to functor in that situation?
Function objects are passed by value in standard algorithms. This means that the derivedFunctor object will be passed by value as a baseFunctor. Since baseFunctor is an abstract class that code cannot compile. (If it was not an abstract class the code would compile, but probably misbehave because of the object slicing problem.)
In order to make this work, you can use something like std::reference_wrapper:
std::make_heap(vectorA.begin(),vectorA.end(),std::ref(*functor));
This works because the reference wrapper object avoids copying the functor and keeps a reference instead; and because it is directly callable and simply forwards arguments to the object reference.

Resources