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.
Related
I was thinking about about template specialization and was wondering if there was a way to use partial specialization to generate two different code paths that are automatically merged.
In this case I have a computational engine where I want an enum to select different functions at compile-time. In this case, depending on the policy or scheme I want different functions at compile-time.
I was thinking that I could avoid explicitly partially specializing all variants. Is this possible?
I've included a small code sample.
#include <iostream>
enum class scheme { linear, polynomial };
enum class policy { no_checking, raise_exception };
struct computational_base
{
void left();
void middle();
void do_stuff()
{
left();
middle();
}
};
template <scheme scheme, policy left>
struct computational_backend : public computational_base
{
};
template <policy left>
struct computational_backend<scheme::linear, left> : public computational_base
{
void middle()
{
std::cout << "scheme::linear" << std::endl;
}
};
template <scheme scheme>
struct computational_backend<scheme, policy::no_checking> : public computational_base
{
void left()
{
std::cout << "policy::no_checking" << std::endl;
}
};
int main()
{
//Ideally would select middle() from first template, and left() from second template
// more than one partial specialization matches the template argument list
computational_backend<scheme::linear, policy::no_checking> what;
what.do_stuff();
return 0;
}
CRTP and multiple inheritance can be your friend. At the core, you can use multiple inheritence to bring functionality in from both classes
template <scheme s, policy p>
struct computational_backend
: scheme_backend<s>
, policy_backend<p>
{ };
This sort of thing will work, as long as the different parts of the computational process don't need to call eachother. In other words, it works when middle() never needs to call left(), and vice versa.
If you need them to call each other, the Curiously Recursive Template Pattern (CRTP) is your friend. This is an oddity which basically lets you cast to the most derived type from the base classes because you pass that most derived type in as a template parameter. It looks like this:
template <typename DerivedT, scheme s>
struct scheme_backend;
template <typename DerivedT, policy p>
struct policy_backend;
template <typename DerivedT>
struct scheme_backend<DerivedT, scheme::linear>
{
DerivedT& derived()
{
return *static_cast<DerivedT*>(this);
}
void left()
{
...
derived().middle();
...
}
};
template <scheme s, policy p>
struct computational_backend
: scheme_backend<computational_backend<s, p>, s>
, policy_backend<computational_backend<s, p>, p>
{ };
I only drew one of the specializations, but you get the idea. It turns out that strange static cast is not only legal in C++, it is, in fact, extraordinarily fast. In many cases, the compiler can optimize it away completly.
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.
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.
I have a templated matrix class that I explicitly instantiate for various POD types and custom class types. Some of the member functions however don't make sense for a few of such custom types. For example:
Matrix<int> LoadFile(....); // This makes sense
Matrix<My_custom_class> LoadFile(...); //This doesn't make sense in the context of the custom class
Can I prevent the instantiation of the LoadFile function (which is a member function) for Matrix objects of select types? So far I have avoided the issue by making LoadFile a friend function and then explicitly controlling its instantiation. But I want to know if I can do this when LoadFile is a member function of Matrix.
The first question is whether you really need to control this. What happens if they call that member function on a matrix that stores My_custom_class? Can you provide support in your class (or the template) so that the member function will work?
If you really want to inhibit the use of those member functions for some particular type, then you can use specialization to block the particular instantiation:
template <typename T>
struct test {
void foo() {}
};
template <>
inline void test<int>::foo() = delete;
Or even just add static_asserts to the common implementation verifying the preconditions for what types is it allowed or disallowed?
template <typename T>
struct test {
void foo() {
static_assert(std::is_same<T,int>::value || std::is_same<T,double>::value,
"Only allowed for int and double");
// regular code
}
};
with std::enable_if, this is the best I can come up with
template< typename T >
struct Matrix {
template< typename T >
Matrix< typename std::enable_if<std::is_integral<T>::value, T>::type >
LoadFile()
{
return Matrix<T>();
}
};
Matrix<int> a;
Matrix<int> b = a.LoadFile<int>()
only type int compile while other don't.
Can I prevent the instantiation of the LoadFile function (which is a member function) for Matrix objects of select types?
Your best bet here would be to use a static_assert that would create a compiler error when you attempt to call the method in a version of the class instantiated with a blocked type. Using std::enable_if, and other methods that would selectively "disable" a method itself would require you to create partial or full specializations of the class with and without the methods in question in order to prevent compiler errors. For instance, AFAIK, you cannot do the following:
template <typename T>
struct test
{
static const bool value = false;
};
template<>
struct test<double>
{
static const bool value = true;
};
template<typename T>
struct example
{
void print() { cout << "Printing value from print()" << endl; }
typename enable_if<test<T>::value, T>::type another_print()
{
cout << "Printing value from another_print()" << endl;
return T();
}
};
If you attempted to instantiate an example<int>, etc., you would end up with a compiler error at the point of instantiation of the object type. You couldn't simply call example<int>::print() and be okay, and only run into a problem if you chose to call example<int>::another_print(). Specializations of example<T> could get you around the issue, but that can be a bit of a mess. As originally surmised, a static_assert would probably be the easiest case to handle, along with a nice message to the end-user explaining what went wrong.
Keep in mind that creating compiler errors is the goal, and it's a good one to have. If you blocked a method from being instantiated, and the end-user decided to invoke it, you'd end up with a compiler error either way. The version without the static_assert will leave a lot of head-scratching as the user of your class attempts to parse a probably very verbose compiler error message, where-as the static_assert method is direct and to the point.
If the selected set of types is known at compile time, and you are using c++11 with a compiler that supports type aliases, uniform initialization and constexpr (for example gcc 4.7) you can make your code a bit cleaner like this (from previous example above by yngum):
template <bool Cond, class T = void>
using enable_if_t = typename std::enable_if<Cond, T>::type;
template< typename T >
struct Matrix {
template< typename T >
//std::is_integral has constexpr operator value_type() in c++11. This will work thanks to uniform init + constexpr. With the alias, no more need for typename + ::type
Matrix<enable_if_t<std::is_integral<T>{}>>
LoadFile()
{
return Matrix<T>();
}
};
Matrix<int> a;
Matrix<int> b = a.LoadFile<int>();
Beware of compatibility of this code, though, because these features have been only recently supported and some compilers don't do yet. You can see more about c++11 compiler support here.
If you could use the TypeLists from the ( http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315 ) - Loki you could implement something like:
template<bool>
struct Static_Assert;
template<>
struct Static_Assert<true>{};
class B{};
template<typename T>
class A{
public:
A(){
Static_Assert< 0 == utils::HasType<T, TYPELIST_2(B,int) >::value >();
}
};
Then your HasType would be something like:
template<typename T, typename TList>
struct HasType{
enum { value = 0+HasType< T, typename TList::Tail >::value };
};
template<typename T>
struct HasType< T, NullType >{
enum { value = 0 };
};
template<typename T, typename U>
struct HasType< T, TypeList<T, U> >{
enum { value = 1 };
};
In the list you can add the classes which you would like prevent to be passed as the template parameters.
Consider the following contrived example of a templated array definition:
template <typename t, unsigned int n> class TBase
{
protected:
t m_Data[n];
//...
};
template <typename t, unsigned int n> class TDerived : public TBase<t, n>
{
TDerived()
{
}
};
I can specialize this type to provide a non-default constructor for an array of length 2 as follows:
template <typename t> class TDerived<t, 2> : public TBase<t, 2>
{
public:
TDerived(const t& x0, const t& x1)
{
m_Data[0] = x0;
m_Data[1] = x1;
}
};
int main()
{
TDerived<float, 2> Array2D_A(2.0f, 3.0f); //uses specialised constructor
TDerived<float, 3> Array3D_A; //uses default constructor
return 0;
}
Is there some other way I can create a class that has different constructor options constrained against template parameters at compile-time without the requirement for a complete class specialisation for each variation?
In other words, is there some way I can have specialised constructors in the TBase class without the need for the intermediary step of creating TDerived whilst preserving the functionality of TBase?
I think deriving your class from a base class is not relevant to the question here, that's a mere implementation detail. What you really seem to be after is if there's a way to partially specialize member functions, like the constructor. Do you want something like this?
template <typename T, int N> class Foo
{
Foo(); // general
template <typename U> Foo<U, 2>(); // specialized, NOT REAL CODE
};
This doesn't work. You always have to specialize the entire class. The reason is simple: You have to know the full type of the class first before you even know which member functions exist. Consider the following simple situation:
template <typename T> class Bar
{
void somefunction(const T&);
};
template <> class Bar<int>
{
double baz(char, int);
};
Now Bar<T>::somefunction() depends on T, but the function only exists when T is not int, because Bar<int> is an entirely different class.
Or consider even another specialization template <> class Bar<double> : public Zip {}; -- even the polymorphic nature of a class can be entirely different in a specialization!
So the only way you can provide specializations new declarations of members, including constructors, is by specializing the entire class. (You can specialize the definition of existing functions, see #Alf's answer.)
There are basically two options I see for this:
Use a variadic function for construction (ie. "..." notation), you can use the value n inside that function to get your arguments from the stack. However, the compiler will not check at compile time if the user provides the correct number of arguments.
Use some serious template magic to allow a call chaning initialization, that would look like this: vector(2.0f)(3.0f). You can actually build something that at least ensures the user does not provide too many arguments here. However tha mechanism is a little more involved, I can assemble an example if you want.
You can always specialize a member, e.g.
#include <stdio.h>
template< class Type >
struct Foo
{
void bar() const
{ printf( "Single's bar.\n" ); }
};
template<>
void Foo< double >::bar() const
{ printf( "double's bar.\n" ); }
int main()
{
Foo<int>().bar();
Foo<double>().bar();
}
But you want effectively different signatures, so it's not directly a case of specializing a member.
One way forward is then to declare a constructor with a single argument, of a type dependent on the template parameters.
Then you can specialize that, as you want.
Cheers & hth.,
Since constructor is a function, you need to fully specialize the containing class to address your specific problem. No way out.
However, functions cannot be partially specialized (in all compilers). So suppose if you know that you need n = 2 when t = int or double then following is one alternative.
template<>
TDerived<int,2>::TDerived()
{
//...
}
template<>
TDerived<double,2>::TDerived()
{
//...
}
and so on.
[Note: If you use MSVC, then I think it supports partial specialization; in that case you can try:
template<typename t>
TDerived<t,2>::TDerived()
{
//...
}
though, I am not sure enough for that.]
You could give the most common definitions in the non-specialized class and static_assert (BOOST_STATIC_ASSERT for non C++0x) on the array length. This could be considered a hack but is a simple solution to your problem and safe.
template<typename T, unsigned int n>
struct Foo {
Foo(const T& x) { static_assert(n == 1, "Mooh!"); }
Foo(const T& x1, const T& x2) { static_assert(n == 2, "Mooh!"); }
};
The "evil" way would be variadic arguments.
template<typename T, unsigned int n>
struct Foo {
Foo(...) {
va_list ap;
va_start(ap, n);
for(int j=0; j < n; ++j)
bork[j] = va_arg(ap, T);
va_end(ap);
}
};
Then there is also C++0x and the good old make_something trick which is more difficult then one would think.
template<typename... T, unsigned int n>
Foo<T, n> make_foo(T&&...) {
// figure out the common_type of the argument list
// to our Foo object with setters or as a friend straight to the internals
Foo< std::common_type< T... >::type, sizeof(T) > foo;
// recursive magic to pick the list apart and assign
// ...
return foo;
}