Specialization of single template argument - c++

Consider the following code:
/* aclass.h */
class AClass
{
public:
template<size_t N, class Vector>
void aMethod(const Vector &);
};
/* aclass.inl */
// method for any N
template<size_t N, class Vector>
void AClass::aMethod(const Vector &) { ... }
// method for N = 1
template<class Vector>
void AClass::aMethod<1>(const Vector &) { ... }
/* main.cpp */
int main()
{
AClass inst;
std::vector<float> data;
// calls method for any N
inst.aMethod<20>(data);
// calls method for N = 1
inst.aMethod<1>(data);
}
I can't seem to find the correct syntax for specializing a single template argument of integer type - and not even sure if it is legal. I looked around a bit, but didn't find anyone with this problem...
These are the errors i get (from msvc):
error C2244 : 'AClass::aMethod' : unable to match function definition to an existing declaration
error C2768 : 'AClass::aMethod' : illegal use of explicit template arguments
How would i go on about solving this problem?

There ain't no such thing as a partial specialization of a function template.
To achieve your goal, you could go through a helper class, which can be partially specialized:
class AClass;
template<size_t N, class Vector>
struct AMethodHelper {
static void Do(AClass* pThis, const Vector&) {
// General for N != 1
}
};
template<class Vector>
struct AMethodHelper<1, Vector> {
static void Do(AClass* pThis, const Vector&) {
// Special for N == 1
}
};
class AClass
{
public:
template<size_t N, class Vector>
void aMethod(const Vector & v) {
AMethodHelper<N, Vector>::Do(this, v);
}
};
Or, you could use two overloads selected with SFINAE:
class AClass
{
public:
template<size_t N, class Vector>
typename enable_if<N!=1>::type aMethod(const Vector &) {
// General for N != 1
}
template<size_t N, class Vector>
typename enable_if<N==1>::type aMethod(const Vector &) {
// Special for N == 1
}
};
Or, I suppose, you could just have one method with if (N == 1) inside. I suspect any decent compiler would be smart enough to eliminate dead code in any given instantiation.

Related

Computing the linear index of a multi-dimensional array when using the curiously recurring template pattern (CRTP)

I am writing a multi-dimensional array class in C++ and would like to have static and dynamic memory versions of it. Based on an answer from one of my previous posts, I used CRTP to define a base class which then has access to the respective data containers (std::array and std::vector) with contiguous memory in the derived classes.
I wish to implement the multi-dimensional subscript operator (e.g. to access the (1, 2) entry of a 4x3 matrix whose 12 entries are stored contiguously in memory) in the base class itself so as to avoid code duplication. Note that I just picked the subscript operator as it is the simplest class method that illustrates what I wish to achieve. I have attempted to adapt the multi-dimensional subscript linearisation solution given here by #Jarod42 to my case with CRTP. However, I am unsure about how to store the array dimensions in the derived classes in order to infer them in the base class when computing the linearised index. I hope the following code demonstrates my issue clearly (I am compiling with C++20):
#include <array>
#include <cassert>
#include <vector>
/** Multi-dimensional Array Base Class with CRTP. */
template <class derived, class T>
class MultiDimArray
{
private:
constexpr derived& Derived() noexcept { return static_cast<derived&>(*this); }
constexpr const derived& Derived() const noexcept { return static_cast<const derived&>(*this); }
protected:
constexpr MultiDimArray() {}
public:
// I've butchered the syntax in the following subscript operators, but I hope it captures what I intend to do.
constexpr const T& operator()(HookTypeToPack<Derived().Dimensions, std::size_t> ...Is) const {
return *(this->Derived()[ComputeIndex<Derived().Dimensions...>(Is...)]);
}
constexpr T& operator()(HookTypeToPack<Derived().Dimensions, std::size_t> ...Is) {
return *(this->Derived()[ComputeIndex<Derived().Dimensions...>(Is...)]);
}
};
/** Static Multi-dimensional Array Class */
template <class T, std::size_t ...Dims>
class StaticMultiDimArray : public std::array<T, (Dims * ...)>,
public MultiDimArray<StaticMultiDimArray<T, (Dims * ...)>, T>
{
private:
constexpr static std::size_t nEntries = (Dims * ...);
constexpr static std::tuple<HookTypeToPack<Dims, std::size_t>...> Dimensions = std::make_tuple(Dims...);
friend MultiDimArray<StaticMultiDimArray<T, (Dims * ...)>, T>;
public:
constexpr StaticMultiDimArray() : std::array<T, nEntries>(InitStaticArray<T, nEntries>(0.0)) {}
};
/** Dynamic Multi-dimensional Array Class */
template <class T>
class DynamicMultiDimArray : public std::vector<T>, public MultiDimArray<DynamicMultiDimArray<T>, T>
{
private:
std::size_t nEntries;
std::tuple<...> Dimensions; // Not sure what to use here considering a tuple is immutable
friend MultiDimArray<DynamicMultiDimArray<T>, T>;
public:
DynamicMultiDimArray() : std::vector<T>() {}
template <typename ...Dims>
DynamicMultiDimArray(Dims ...dimensions) : std::vector<T>((dimensions * ...), 0.0) { Resize(dimensions...); }
template <typename ...Dims>
void Resize(Dims ...dimensions)
{
nEntries = (dimensions * ...);
this->resize(nEntries);
// store dimensions in Dimensions...
}
};
The support functions InitStaticArray, HookTypeToPack, and ComputeIndex used above are defined as follows:
template <class T, std::size_t size>
constexpr auto InitStaticArray(const T& value)
{
std::array<T, size> arr;
std::fill(arr.begin(), arr.end(), value);
return arr;
}
template <std::size_t, typename T>
using HookTypeToPack = T;
template <std::size_t ...Dims>
constexpr std::size_t ComputeIndex(HookTypeToPack<Dims, std::size_t> ...multi_index)
{
constexpr std::size_t dims_arr[] = {Dims...};
std::size_t multi_index_arr[] = {multi_index...};
std::size_t index(0), factor(1);
for(int i = 0; i < sizeof...(Dims); i++)
{
assert(0 <= multi_index_arr[i] && multi_index_arr[i] < dims_arr[i]);
index += factor * multi_index_arr[i];
factor *= dims_arr[i];
}
assert(0 <= index && index < (Dims * ...));
return index;
}
Can anyone give me some advice on how to store the array dimensions in StaticMultiDimArray and DynamicMultiDimArray so they can be appropriately invoked in the operator() overloads in MultiDimArray?
There are several options. One you are already hinting at: store the dimensions in the derived class. However, don't use a std::tuple; that allows every element to have a different type, while we just want the size of every dimension to be a std::size_t. Use a std::array for the static array, std::vector for the dynamic one:
template <class T, std::size_t ...Dims>
class StaticMultiDimArray :
public std::array<T, ...>,
public MultiDimArray<...>
{
constexpr static std::array dimensions{Dims...};
...
};
template <class T>
class DynamicMultiDimArray :
public std::vector<T>,
public MultiDimArray<...>
{
std::vector<std::size_t> dimensions;
...
};
You also don't need to make the constructor of DynamicMultiDimArray a template, instead you can have it take a std:initializer_list as an argument, like so:
DynamicMultiDimArray(std::initializer_list<std::size_t> dimensions) :
std::vector<T>(std::accumulate(dimensions.begin(), dimensions.end(), std::size_t{1}, std::multiplies<std::size_t>())),
Dimensions(dimensions) {}
Yeah, the initialization of the actual vector of elements looks very ugly now. I would recommend not using inheritance for this, but composition. Then you can initialize the dimensions first, then the array/vector of data, and can make a member variable in MultiDimArray that calculates the number of entries:
template <class derived, class T>
class MultiDimArray {
...
constexpr std::size_t nEntries() const {
const auto &dimensions = Derived().dimensions;
return std::accumulate(dimensions.begin(), dimensions.end(), std::size_t{1}, std::multiplies<std::size_t>());
}
...
};
template <class T>
class DynamicMultiDimArray :
public MultiDimArray<...>
{
std::vector<std::size_t> dimensions;
std::vector<T> data;
...
public:
DynamicMultiDimArray(std::initializer_list<std::size_t> dimensions) :
Dimensions(dimensions),
data(nEntries()) {}
};
Similarly, you can make operator() take a std::initializer_list<std::size_t> for the indices. Code using this looks like so:
DynamicMultiDimArray dimarr({3, 5, 7}); // create new array
...
std::cout << dimarr({1, 2, 3}) << '\n'; // print element at index 1, 2, 3
This avoids a lot of template hassle. You could even consider creating a custom multi-dimensional index type instead of a std::initializer_list<std::size_t>, making it easier to store indices in a variable and pass them around.

How to write the scope resolution operator function header for nested classes?

Hey I have a fairly simple question that some quick google searches couldnt solve so I'm coming here for some help.
I'm having trouble just getting my assignment off the ground because I can't even write the skeleton code!
Basically I have a header file like so:
namespace foo{
class A {
public:
class B {
B();
int size();
const int last();
};
};
}
And I want to know how to refer to these guys outside of the file in a implementation file.
BONUS:
namespace foo{
template<typename T>
typename
class A {
public:
class B {
B();
int size();
const int last();
};
};
}
how are these functions referred to as?
Is there a formula I can follow when it comes to this or is it more of flexible, different for your needs kinda thing?
Thanks for the help!
I'm using visual studios if that changes anything...
Given:
namespace foo{
class A {
public:
class B {
B();
int size();
const int last();
};
};
}
The complete name for a function definition of size or last would be:
int foo::A::B::size() {...}
const int foo::A::B::last() {...}
Given:
namespace foo{
template<typename T>
typename
class A {
public:
class B {
B();
B & operator ++();
int size();
const int last();
template< typename I, typename R>
R getsomethingfrom( const I & );
};
};
}
The function definitions would be:
template <typename T> int foo::A<T>::B::size() { ... }
template <typename T> const int foo::A<T>::B::last() { ... }
For these, getting the pointer to a member function would be:
auto p = &foo::A<T>::B::size;
Constructor definition would be:
template<typename T> foo::A<T>::B::B() {}
Making one of these things:
foo::A<T>::B nb{}; // note, with nb() it complains
The operator function definition returning a reference to a B, in the template, tricky:
template<typename T> // standard opening template....
typename foo::A<T>::B & // the return type...needs a typename
foo::A<T>::B::operator++() // the function declaration of operation ++
{ ... return *this; } // must return *this or equivalent B&
In case you're curious, if a template function is inside B, like getsomethingfrom, then definition of the function is:
template< typename T> // class template
template< typename I, typename R> // function template
R foo::A<T>::B::getsomethingfrom( const I & ) // returns an R, takes I
{ R r{}; return r }
To use the class in your implementation (.cpp) file you go likes that:
namespace foo{
A::B::B(){
// this is your inner class's constructor implementation
}
int A::B::size(){
// implementation for you size()
int res = last(); // access the method last() of the same object
return res;
}
const int A::B::last(){
// implementation of last()
return 42;
}
}
void main(){
foo::A a; // construct an object of A
// can't do anything useful as the methods of A::B are all private
}

Template parameters simplification

I am fairly new to C++ (using C++ 2011) and I would like to find a solution for the following problem. I have a class that represents a fonction:
class Curve {
private:
...
public:
std::array<double, 3> value(double s);
}
I am using that object to pass this function to an algorithm that is represented by a class:
template <int n, typename Functor>
class Algorithm {
private:
Functor f;
std::array<double, n> a;
public:
...
}
Then I create the object
Algorithm<3, Curve> solver;
But the 3 is obviously the 3 coming from the size of the array returned by the method value of any objet of type Curve. I would like to simplify this code so that I can use :
Algorithm<Curve> solver;
But I have no idea on how to do that. Would you mind giving me a hint ?
Best regards,
Francois
Add a member array_length or something similar to the Curve like classes:
class Curve
{
public:
static constexpr const std::size_t length = 3;
private:
std::array<double,length> a;
};
template<typename ALGORITHM , std::size_t n = ALGORITHM::length>
class Algorithm
{
...
};
If you need to allow classic function entities as algorithms, that approach doesn't work since there is no length member. Other way could be to create a metafunction data_length
which given a algorithm function F returns the length of the data:
template<typename F>
struct length;
//Specialization for Curve class:
template<>
struct length<Curve> : public std::integral_constant<std::size_t,3>
{};
And then:
template<typename F , std::size_t n = length<F>::value>
struct Algorithm
{
...
};
EDIT: Like in any other template, to implement the method specify its template parameters:
template<typename F , std::size_t N>
void Algorithm<F,N>::execute()
{
_f();
}
Here is a running example.
Use decltype to get the return type of value, and std::tuple_size to find out how big it is (Live at Coliru):
template <typename Functor>
class Algorithm {
private:
Functor f;
static const std::size_t n =
std::tuple_size<decltype(f.value(0.))>::value;
std::array<double, n> a;
public:
// ...
};
or if you simply want a to have the same type that value returns:
template <typename Functor>
class Algorithm {
private:
Functor f;
decltype(f.value(0.)) a;
public:
// ...
};
or if you might someday want to use functions of a different type - say int or long long or whatever - you can ask for the return type of f.value when invoked with a default-constructed value of whatever its argument type happens to be:
template <typename Functor>
class Algorithm {
private:
Functor f;
decltype(f.value({})) a;
public:
// ...
};
You could "pass" the 3 in an enum member like this:
class Curve {
public:
enum { arity = 3 };
std::array<double, arity> value(double s);
};
template <typename Functor>
class Algorithm {
private:
std::array<double, Functor::arity> a;
};
Curve curve;
Algorithm<Curve> solver;

C++ - specialising member function template via templated functor does not compile

I wish to create a class that can convert between arrays of floats and doubles polymorphically. That is, the instance concerned (parameterised by <double> or <float>) and the decision to pass a float* or double* is decided at runtime, not statically.
As a proposed answer to another question, but modified according to this answer (because I understand it's not possible to fully specialise a member function template inside a class), a pure virtual base class BaseDest that provides simple overloaded member functions is sub-classed to define DestImpl<T>. I use this base class to maintain a dynamic collection of DestImpl<T> instances, with varying T. This class provides explicit overloads of the assign() member function; one for a double *, and another for a float *. The idea is that at run-time, BaseDest::assign() is called via a polymorphic pointer or reference, and this in turn calls the correct virtual assign() member function in DestImpl<T>.
Now, it is important that then the non-pointer type of the array matches T in DestImpl<T>, that a fast_copy() function is called (perhaps a memcpy), and when the types do not match a slower statically-cast-item-by-item copy is performed. So the assign() member function offloads this to a templated functor. There are two specialisations for this functor - one where the type parameter of the functor matches the type of DestImpl<T> (and therefore invokes a fast copy), and a fall-back one that catches all other cases (and invokes a slow copy).
However, I am unable to get the following code to compile. The comments show where the compiler error and warning appear - I suspect they are related. What I don't understand is why the second specialisation of apply_helper is unable to be instantiated as apply_helper<double>.
class BaseDest {
public:
virtual ~BaseDest() {}
virtual void assign(const double * v, size_t cnt) = 0;
virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
void assign(const double * v, size_t cnt) {
assign_helper<T>()(v, cnt);
}
void assign(const float * v, size_t cnt) {
assign_helper<T>()(v, cnt); // ERROR: no matching function for call to object of type 'assign_helper<double>'
}
protected:
template <typename U>
struct assign_helper {
void operator()(const U * v, size_t cnt) {
for (size_t i = 0; i < cnt; ++i) {
//slow_copy(v[i]);
}
}
};
template <typename U>
struct assign_helper<T> { // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
void operator()(const T * v, size_t cnt) {
//fast_copy(v, cnt);
}
};
};
void test() {
DestImpl<double> d; // error mentioned above appears when this is present
}
EDIT: here's something that does seem to work - moving the assign_helper struct (now a class) out of the DestImpl<T> class definition. I'm not sure this is the right way to do it, but it does seem to work so far:
// slow copy between different types
template <typename T, typename U>
class assign_helper {
public:
void operator()(const U *v, size_t cnt) {
// slow copy
}
};
// fast copy between same types
template <typename T>
class assign_helper<T, T> {
public:
void operator()(const T * v, size_t cnt) {
// fast copy
}
};
class BaseDest {
public:
virtual ~BaseDest() {}
virtual void assign(const double * v, size_t cnt) = 0;
virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
virtual void assign(const double * v, size_t cnt) {
assign_helper<T, double>()(v, cnt);
}
virtual void assign(const float * v, size_t cnt) {
assign_helper<T, float>()(v, cnt);
}
};
template <typename U>
struct assign_helper<T> { // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
The above is the cause of your error. The warning explicitly tells you that this definition will never be used. What you want instead of template < typename U > is template <>.

C++ - Template Specialization & Partial Specialization

I have been looking all over the internet and stackoverflow for a concrete answer but I can't seem to find one. I have to create a generic class and then implement specific functions. My specific instructions were: You need to make use of Template Expression Parameters and Template Class Specialization and Partial Specialization.
I have a template class:
template <class T, int x, int y>
class Z {
T **array[x][y];
public:
Z();
void print();
//and other methods
};
I need to:
1) Only Z's where x= 2 and y = 2 need to have a public method void J()
2) For char Z's of x = 2 and y= 2 J will do something; for everything else it does something else
3) For only Z's where T is char will the array be initialized to some value. For everything else it's 0
Naturally, this works:
template<class T, int x, int y>
Z<T,x,y>::Z<T,x,y>() { //initialize to 0 }
But this doesn't:
template<int x, int y>
Z<char,x,y>::Z<char,x,y>() { //initialize to something}
And likewise (assume J exists) this does not work:
template <class T>
void Z<T,2,2>::J() { //something }
My question is:
Is there any simple method for implementing the above items? I need to keep all the other methods in Z. Giving a hint or pointing in the right direction (maybe I missed a question since there are a lot) would be helpful.
Thanks.
It seems you want to define only some functions of some specializations : if print() does not change between the char specialization and the general case, it seems that you don't want to redefine it.
// What you want to do (illegal in C++)
template<int,typename T>
struct Z
{
T myValue;
Z();
void print() { /* ... */ }
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }
template<int i>
Z<i,char>::Z() { /* ... */ }
However, it does not work like this. Partial or full specializations of class have almost nothing in common, except 'prototype' of template parameters:
// The two following types have only two things related: the template parameter is an int,
// and the second type is a full specialization of the first. There are no relations between
// the content of these 2 types.
template<int> struct A {};
template<> struct A<42> { void work(); };
You have to declare and define each (partial) specialization:
// Fixed example
template<int,typename T>
struct Z
{
T myValue;
Z();
void print() { /* ... */ }
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }
// Specialization for <all-ints,char>
template<int i>
struct Z<i,char>
{
char myValue;
char othervalue;
Z();
void print() { /* Same code than for the general case */ }
};
template<int i>
Z<i,char>::Z() { /* ... */ }
The only way to escape the code duplication is by using inheritance of traits:
// Example with the print function
template<typename T>
struct print_helper
{
void print() { /* ... */ }
};
// Fixed example
template<int,typename T>
struct Z : public print_helper<T>
{
T myValue;
Z();
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }
// Specialization for <all-ints,char>
template<int i>
struct Z<i,char> : public print_helper<char>
{
char myValue;
char othervalue;
Z();
};
template<int i>
Z<i,char>::Z() { /* ... */ }
You cannot do what you want without duplication for the moment (the feature removing code duplication is static if and has been proposed for the next C++ standard, see n3322 and n3329).
You may have a look at this course http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-5-of-n
While this is not possible that you define partial specialization for function templates, you can define partial specialization for class or struct template.
template<typename T> struct helper {
static void doThingy(){}
};
template<typename X> struct helper<X*> {
static void doThingy(){}
};
Helper(double*)::doThingy();
In this example, you want to specialize behavior in doThingy() only when the type in template is a pointer type. You cannot use overload of method doThingy() in this case. This is because you cannot overload a function with no arguments. But you can have partial specialization of the struct helper. In specialized template, you implemented wished behavior for the doThingy().