1

This is a continuation off of this original question here: Original Question that was focused more towards a design decision. This question is more to the actual how to towards the implementation if it can even be done.

I have this in my current source:

template <typename ClassType,typename... Dimensions>
class DimensionPack {
public: 
    typename std::tuple<ClassType, std::tuple<Dimensions...> >::type Dim;
    const unsigned int numarguments = sizeof...(Dimensions);
};

That would be used with a series of classes that are related with the following prototypes:

template<typename ClassType, typename... Args>  class MatrixReference;
template<typename ClassType, typename... Args>  class MatrixStorage;
template<typename ClassType, typename... Args>  class MatrixAllocation;

I have already been asked why couldn't I just use std::size_t...

After considerable thought I'm still leaning towards using the variadic parameter pack with the helper template that would store it into an std::tuple to help pack and unpack the parameters. Also I have a need to test these parameters to be in the range of {x; x > 0} so they must all be + integers. So the parameter pack itself or the contents of it can be either std::size_t or unsigned int but they all need to be one or the other. I also need to test these parameters to check if their value is even or odd and to save those results into a container. The use of a helper function will do that for me.

Knowing this I'm leaning towards staying with the parameter pack so I can easily pass that pack as a reference from one template to another since the set of these templates will work together, and I can also pass the parameter pack to my helper function to test for odd and even values.

So the questions become:

  • Can a parameter pack with <typename... Args> be restricted to a specific type such as std::size_t or unsigned int?
  • If so, how can this be done?
  • If not what are my options towards achieving this?
Community
  • 1
  • 1
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 3
    Possible duplicate of [Variadic template parameter pack to accept only unsigned ints or size\_t as its type](http://stackoverflow.com/questions/41993864/variadic-template-parameter-pack-to-accept-only-unsigned-ints-or-size-t-as-its-t) – O'Neil Feb 02 '17 at 07:18
  • O'Neil I added that it was a continuation of the first question, however instead of making a choice between one or the other; I'm asking here if it is possible and if so how? – Francis Cugler Feb 02 '17 at 07:32
  • http://stackoverflow.com/questions/39659127/restrict-variadic-template-arguments/39659128#39659128 Although that is about function parameters, the concepts there can be easily applied to your case. – bolov Feb 02 '17 at 09:02
  • I propose to close the Original Question, keeping it as a reference for historical purposes and to accept this question as the actual question at hand. – Francis Cugler Feb 03 '17 at 13:10
  • @FrancisCugler Questions are both yours, so you are free to do that. – skypjack Feb 03 '17 at 20:19

1 Answers1

2

Can a parameter pack with  be restricted to a specific type such as std::size_t or unsigned int?

The bool trick does it in a compact way.
As a minimal, working example:

#include <type_traits>
#include <utility>

template<typename... Args>
constexpr bool check(Args&&...) {
    return std::is_same<
        std::integer_sequence<bool, true, (std::is_same<std::size_t, std::remove_reference_t<Args>>::value or std::is_same<unsigned int, std::remove_reference_t<Args>>::value)...>,
        std::integer_sequence<bool, (std::is_same<std::size_t, std::remove_reference_t<Args>>::value or std::is_same<unsigned int, std::remove_reference_t<Args>>::value)..., true>
    >::value;
}

int main() {
    static_assert(check(std::size_t{42}, 3u), "!");
    static_assert(not check(std::size_t{42}, 'c'), "!");
}

I used both the types in the check because of your comment (emphasis mine):

So the parameter pack itself or the contents of it can be either std::size_t or unsigned int but they all need to be one or the other

See it running on wandbox.

Note that you can use the same technique to check statically the types used to initialize a class.
As an example:

template<typename... Args>
struct S {
    static_assert(std::is_same<
        std::integer_sequence<bool, true, (std::is_same<std::size_t, std::remove_reference_t<Args>>::value or std::is_same<unsigned int, std::remove_reference_t<Args>>::value)...>,
        std::integer_sequence<bool, (std::is_same<std::size_t, std::remove_reference_t<Args>>::value or std::is_same<unsigned int, std::remove_reference_t<Args>>::value)..., true>
    >::value, "!");
};

In this case, something like this will compile:

S<std::size_t, unsigned int> s;

On the other side, the following will end with an error at compile time:

S<std::size_t, char> s;
skypjack
  • 49,335
  • 19
  • 95
  • 187