Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template method with number of arguments fixed for instantiation but variable by template parameter

Tags:

c++

templates

I'd like to define a function for template class with an integer template parameter so that the number of function arguments depends on the template parameter. Here's an example:

template< class Coord, int dim >
class Point {
    Coord mCoords[ dim ];
public:
    void Set( /* I want exactly dim Coord arguments here. */ );
};

I'd like this code to compile:

Point<double,2> pt2d;
pt2d.Set( 25, 32 );
Point<double,3> pt3d;
pt3d.Set( 25, 32, 100 );

and this code to fail:

Point<double,2> pt2d;
pt2d.Set( 25, 32, 100 );  // Too many arguments
Point<double,3> pt3d;
pt3d.Set( 25, 32 );       // Too few arguments

Now, I can manually specialize Point in smaller dimensions to have unrelated Set functions, but I find the practice of essentially repeating the same code un-C++-ish. Furthermore, I shouldn't have to specialize for every possible value of the int template parameter.

Is it possible to implement Point<Coord,dim>::Set() function that would take exactly dim arguments of type Coord without writing specialization code for each value of dim?

like image 333
Michael Avatar asked Oct 02 '15 17:10

Michael


People also ask

What are template arguments enlist types of template arguments?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

Which is correct example of template parameters?

For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.

Why do we use :: template template parameter?

8. Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.

What is meant by template parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.


1 Answers

You could use the trick that Boost.Hana uses for getNth:

template <typename Coord, int dim, typename = std::make_index_sequence<dim>>
struct Point;

template <typename Coord, int dim, size_t... Ignore>
struct Point<Coord, dim, std::index_sequence<Ignore...>>
{
    void Set(decltype(Ignore, Coord{})... args)
    {
        // ...
    }
};

A longer version that hides the Ignore ugliness a little bit (and works for non-default-constructible Coords... ) would be to add some metaprogramming boilerplate:

template <typename... > struct typelist { };

template <int N, typename T, typename = std::make_index_sequence<N>>
struct repeat;

template <int N, typename T>
using repeat_t = typename repeat<N, T>::type;

template <int N, typename T, size_t... Idx>
struct repeat<N, T, std::index_sequence<Idx...>>
{
    template <size_t >
    struct makeT { using type = T; };

    using type = typelist<typename makeT<Idx>::type...>;
};

And then specialize on repeat_t instead. And hide this in a namespace so a user can't mess it up:

namespace details {
    template <typename Coord, int dim, typename = repeat_t<dim, Coord>>
    struct Point;

    template <typename Coord, int dim, typename... dimCoords>
    struct Point<Coord, dim, typelist<dimCoords...>>
    {
        void Set(dimCoords... args)
        {

        }
    };
}

template <typename Coord, int dim>
using Point = details::Point<Coord, dim>;
like image 98
Barry Avatar answered Dec 03 '22 07:12

Barry