c++11 variadic template method completely shadow base class method? - c++

I have the following problem( see code below).
In a class that inherits from a base class, I want to be able to have two implementations of operator(). One that takes integers, one that takes "indices", see simple Index class.
The operator(ints...) will be in the child class, while I need to have the operator(Index...) in the parent class (also with different return type.)
The code below is not the exact design but a minimal working example explaining the final problem.
Problem is, if I put operator(Index...) in the child class, everything is good. If I put it in the base class, i get a compilation error:
error: no match for call to ‘(Tensor<1, int>) (Index<'i'>&)’
when I call vec(i) and the end of the main(). I understand the compiler doesn't find the good method, but why ? Is there some "shadowing" rule associated to variadic templates ?
Thanks !
#include <iostream>
#include <type_traits>
template<char i>
class Index{
public:
Index(){};
};
template<int order, typename T, class tensor_type>
class Tensor_traits{
public:
//// here, doesn't compile ! !
//template <char i>
//T&operator()(Index<i> &ii){
//std::cout << "puet" << std::endl;
//}
};
template<int order, typename T>
class Tensor : public Tensor_traits<order, T, Tensor<order, T>> {
private:
int data[3] = {1,2,3};
public:
Tensor(){};
template <typename... Idx>
typename std::enable_if<std::is_same<Idx...,int>::value
or std::is_same<Idx...,unsigned int>::value
or std::is_same<Idx...,size_t>::value, T&>::type
operator()(const Idx&... idx){
return data[0]; //dummy here, actually i do other stuff !
}
// here, works!
template <char i>
T&operator()(Index<i> &ii){
std::cout << "puet" << std::endl;
}
};
int main() {
Tensor<1,int> vec1;
std::cout<< vec1(1) << std::endl;;
Index<'i'> i;
vec1(i);
}

Try adding
using Tensor_traits<order, T, Tensor<order, T>>::operator();
or (suggested by Yakk (thanks) to have Base for other uses)
using Base = Tensor_traits<order, T, Tensor<order, T>>;
using Base::operator();
in Tensor
The problem isn't that the base class is a template class; the problem is that the derived class define another operator() method function that hide the operator() method inherited.
To verify this, delete the operator() defined in the derived class and you can see that, also without using, you can use the operator() of the base class.
Using using unhide the operator() of the base class, when an operator() is defined in the derived class, so you can use both.

Related

How do I implement inheritance in a partial class template specialisation?

I think I'm just missing something small. I want to specialize the constructor of a templated class for an implementation where T = the template class with any parameter. Sorry if my vocab is a bit off.
Basically, I need to allow for jagged 2D arrays, so I might have a ArEl<ArEl<int>> and I would like to preinitialise all the array lengths.
using namespace std;
template <typename T>
class ArEl {
public:
ArEl(size_t size = 0)
: rSize(size), rArray(rSize ? new T[rSize]() : nullptr) {}
ArEl(const ArEl& other);
virtual ~ArEl() { delete[] rArray; }
void swap(ArEl& first, ArEl& second);
void redim(size_t size);
private:
std::size_t rSize;
T* rArray;
};
template <typename T, typename T1>
class ArEl<ArEl<T>> : public ArEl<T1>{
ArEl(size_t size = 0);
};
EDIT:
I'm getting this error:
error: template parameters not deducible in partial specialization:
class ArEl<ArEl<T>> : public ArEl<T1>{
You're specializing your object in the wrong way.
template<typename T, typename T1> implies that there's two datatypes that need to be provided, but it's clear that the only thing your template specialization needs is the datatype of the underlying array(s). If the expectation is that ArEl<ArEl<T>> be specialized, it shouldn't take more than this:
template<typename T>
class ArEl<ArEl<T>> {
/*Blah Blah Blah*/
};
There's no need for inheritance, and no need for a second datatype.
However, I'll also add: there's not really any need for this specialization in the first place. If you don't write the specialization at all, the following code should still work as-is:
ArEl<ArEl<int>> dim2Array(50);
//I'm assuming ArEl will have a member size() function
for(size_t index = 0; index < dim2Array.size(); index++) {
//I'm assuming ArEl will have an operator[] overload
dim2Array[index].redim(30);
}
//dim2Array is now 50 int arrays, each of size 30.
I'm assuming that the functionality you're intending is to have something like the following, which does require template specialization like what I posted above:
ArEl<ArEl<int>> dim2Array(50, 30);
//dim2Array is now 50 int arrays, each of size 30.
But if I were you, I'd leave the implementation of ArEl alone and instead invest in writing a Matrix<T> class (or possibly Matrix<T, N>, for N-dimensions) that handles this kind of syntax instead (which you could build using ArEl<T> as the building blocks, incidentally), especially because I don't think you're committed to writing the specializations for ArEl<ArEl<ArEl<int>>> or deeper (and yes, the way you're trying to do it, each level would need its own specialization).
Specializing an entire class implies replacing all the members with the ones provided by the specialization. You don't want that.
One option would be to provide all the members that need specialization in a base class: BaseForA<T> would be specialized, and A<T> would derive from it.
Another one would be to use tag dispatching, here's an example of how you can use it to do different actions depending on the type parameter.
#include <iostream>
#include <type_traits>
template<typename T>
struct tag {};
template<typename T>
struct A
{
private:
template<typename U>
A(std::size_t s, tag<A<U>>)
{
std::cout << "special constructor " << s << "\n";
}
A(std::size_t s, ...)
{
std::cout << "general constructor " << s << "\n";
}
public:
A(std::size_t s = 0) :
A(s, tag<T>())
{
}
};
int main()
{
A<int> a;
A<A<int>> b;
A<A<long>> c;
A<long> d;
}
Live on Coliru
If I understand you correctly you want the specialised version to inherit the generic version and then add something on top of it. The problem here is that you have a specialised ArEl<ArEl<T>>, you cannot request a generic version of it.
The solution is to make the generic version and the specialised version be different types.
template<typename T, bool D=true>
class ArEl { ...
template<typename T>
class ArEl<ArEl<T>>:
public ArEl<ArEl<T>, false> { ...
But now the problem is that ArEl<T, true> and ArEl<T, false> are unrelated and incompatible!
The solution is to introduce a common base class for them.
template<typename T>
class ArElBase {
... all functionality of ArEl
};
template<typename T, bool D=true>
class ArEl : public ArElBase<T> {
using ArElBase<T>::ArElBase;
// nothing more
};
and then the specialisation, unchanged.
Now you can use ArElBase to pass your objects by pointer or reference, but use ArEl to declare objects themselves.

Implementing templated template method

Note: The following question is about the Template Method Design Pattern and C++ function templates. To distinguish both, I will use italics when referring to the design pattern and bold when referring to C++ templates.
The idea of the template method pattern is to make parts of an algorithm exchangeable. This is usually achieved via inheritance, where the subclass provides concrete implementations that are plugged into an algorithm of the base class. However, if the hook methods need to be templates, this will not work as templates cannot be virtual. Here is a simple example that does not compile:
class Base
{
public:
// This is the template method
template <typename T>
void doSomething(T input)
{
//...
auto converted = ConvertInput(input);
//...
std::cout << converted;
}
protected:
//compile error "member function templates cannot be virtual"
template <typename T>
virtual T ConvertInput(T input) = 0;
};
class Derived : public Base
{
protected:
template <typename T>
T ConvertInput(T input)
{
return 2 * input;
}
};
int main()
{
Derived d;
d.doSomething(3);
}
Is there a way to implement template methods that use function template hooks?
I am not interested in using the Base class as a type anywhere. I will always use the concrete specific type to achieve a maximum of compile-time optimization. So another formulation of this question is: How can I create several classes Derived-1 .. Derived-n that have function templates that share a common code skeleton across the implementations?
Sounds like a fine use-case for CRTP. Define Base as a class template with the type derived from it as the template parameter. Inside Base's methods you can cast down to the derived type:
template<typename Derived>
struct Base
{
// This is the template method
template <typename T>
void doSomething(T input)
{
//...
auto converted = static_cast<Derived*>(this)->ConvertInput(input);
//...
std::cout << converted << std::endl;
}
};
And then define the derived types, for example:
struct Square : Base<Square>
{
template<typename T>
auto ConvertInput(T t)
{
return t*t;
}
};
struct Sum : Base<Sum>
{
template<typename T>
auto ConvertInput(T t)
{
return t+t;
}
};
the usage is pretty trivial:
Square sq;
Sum sum;
sq.doSomething(3);
sum.doSomething(3);
live demo
CRTP solves your problem by making Base a template.
If T comes from a finite set, or conversion is non arbutrary, type erasure can work.
If a finite set, type erase all the derived virtual methods. If common property, type erase that property and virtualize method that acts on it. Or a mixture.
Otherwise, Base can have template methods that take the operation as function object (with template operator()) instead of using virtual to find it. Derived passes the templated operations in as arguments to Base method(s). This is basically CRTP without CRTP.

Accessing a member type of an incomplete type

What is the workaround to get this to compile?
#include <iostream>
template <typename Derived>
struct CRTP {
void foo (const typename Derived::type& a) {std::cout << a << '\n';}
};
struct A : CRTP<A> {
using type = int;
};
struct B : CRTP<B> {
using type = std::string;
};
// etc...
int main() {
A a;
a.foo(5);
}
This will not compile, because at the time of instantiation of CRTP<A>, A isn't a complete class yet, so A::type cannot be accessed. But what is the workaround? I need this type of design so that the foo function can be used generically for many different classes.
A somewhat crazier alternative is to defer evaluation until an attempt is made to call foo, by which point Derived would be complete. This requires making it a template.
template <typename Derived>
struct CRTP {
template<class T = Derived>
void foo (const typename T::type& a) {std::cout << a << '\n';}
};
It is trivial to block calling foo with a type that isn't Derived, if desired, via a static_assert.
I'm pretty sure you can't use the CRTP on a 'using' case. You can use it for methods and members, but not things like types. When using templates though, having types as template parameters is what it is so useful for, so why not do
template <typename Derived, typename Type>
....
Which will work perfectly fine.

How to limit template parameters to a descendent that is a specialization of a templated interface?

Assume the following situation:
There is a templated interface defining a set of operations on different data types.
This interface is implemented by various specialized classes defining the operations for actual data types.
There is some managing class that has to work instances of classes as defined in 2.
Simplified example code could look like this:
#include <iostream>
#include <type_traits>
template <typename R, typename S>
class ICanDoIt
{
public:
virtual void doStuff() = 0;
protected:
ICanDoIt<R, S>(R rA, S sA) : r(rA), s(sA) {};
R r;
S s;
};
class DoesIt : public ICanDoIt<int, double>
{
public:
DoesIt(int iA, double dA) : ICanDoIt(iA, dA) {};
virtual void doStuff()
{ std::cout << "r * s = " << r * s << " done." << std::endl; }
};
template <typename T>
class NeedsSomeoneWhoCanDoIt
{
static_assert(std::is_base_of<ICanDoIt<R, S>, T>::value,
"T needs to be able to do it.");
public:
NeedsSomeoneWhoCanDoIt(const T& doesItA) : doesIt(doesItA) {};
void getItDone() { doesIt.doStuff(); };
private:
T doesIt;
};
int main()
{
DoesIt doesIt(5, 2.2);
NeedsSomeoneWhoCanDoIt<DoesIt> needsIt(doesIt);
needsIt.getItDone();
}
If you untemplate the interface "ICanDoIt" the code will actually work. But the static_assert for the templated version will fail because ICanDoIt's template arguments are wrapped and hidden by the specialization performed in the decalaration of DoesIt.
How can I limit the managing classes (NeedsSomeoneWhoCanDoIt) template parameter "T" to any specialization of ICanDoIt, regardless of which type has been chosen for R, S during the specialization of ICanDoIt?
You could always make the actual types for R and S used to instantiate ICanDoIt accessible to a derived class, i.e.
template <typename R, typename S> class ICanDoIt {
public:
typedef R R_t;
typedef S S_t;
virtual void doStuff() = 0;
};
so that your static_assert would become
static_assert(std::is_base_of<ICanDoIt<typename T::R_t, typename T::S_t>,
T>::value,
"T needs to be able to do it.");
Depending on what your actual code looks like the design might become clearer if you'd define a purely abstract base class (i.e. an actual type ICanDoItBase instead of a template) from which you'd inherit the currently templated functionality in ICanDoIt which would again be a base of DoesIt.
NeedsSomeoneWhoCanDoIt could then directly use the the polymorphic base class ICanDoItBase without any needs for additional type checks.
You don't need to publish the template parameters. The standard SFINAE-based approach would work just fine.
namespace detail {
template<class R, class S>
std::true_type test(ICanDoIt<R, S>*);
std::false_type test(...);
}
template<class T>
using can_do_it = decltype(detail::test((T*)nullptr));

Specialized function in non specialised Template class

Please refer to the below code
Specialized function in non specialized Template class
Is it possible to write a specialized function foo, for non specialized template class MyClass [Line Number 7] ? If yes, then, what is the syntax for the same.
Regards,
Atul
This can be done if you create a full specialization of the class template. Just refer to the answer in this question: If I want to specialise just one method in a template, how do I do it?
Otherwise if you want to have a given function with the same signature have two different behaviors depending on the instantiated version of the class, and that instantiation is a partial specialization of the template class, you will have to make a separate specialization of the template class.
Keep in mind that if you want to avoid redundant code in this second case, you can always create a base template class that will have the functionality that will not change, and then create derived template classes that will contain the unique functionality necessary for each partial specialization.
Look at my example below, I have tried answer your question (if I guessed right) in the simplest code possible by me:
#include <iostream>
using namespace std;
template<typename T>
class Some
{
public:
template<typename U> void foo(U val);
};
template<typename T>
template<typename U>
void Some<T>::foo(U val)
{
cout << "Non specialized" << endl;
}
template<>
template<>
void Some<char>::foo(char val)
{
cout << "Char specialized" << endl;
}
int main()
{
Some<int> t1;
t1.foo(5);
Some<char> t2;
t2.foo('c');
return 0;
}
The important thing to note here is that "You cannot specialize your class and function Independently" i.e you have to specialize both at the same time as done in the example.
Also, with this you lose the opportunity to specialize your class for that data type "char" in this case. (Need to confirm on this).
UPDATE :: Confirmed on point 2.
If you wanted to specialize MyClass< bool >::Foo, it would look like this:
template <>
void MyClass<bool>::Foo(bool A)
{
// code goes here
}
If you are asking that,
(1) you want a function Foo() which doesn't take any argument and
returns void inside MyClass
(2) This Foo() should be exclusive to the MyClass when the
template type is bool, i.e. only for MyClass<bool>
then here is the way:
template<class Precision>
class MyClass {
...
public:
...
void Foo (); // don't implement here
};
...
template<>
void MyClass<bool>::Foo () // implementing only for 'MyClass<bool>'
{ // invoking for other 'MyClass<>' will result in compiler error
...
}