I want to write a class which is templated by a number of dimensions:
namespace detail {
enum class enabler {};
}
template<size_t dim>
class templateClass
{
public:
template<class... DimArgs, typename std::enable_if<sizeof...(DimArgs)==dim, detail::enabler>::type...>
templateClass(DimArgs... dimensions) {
// Use integers passed to the constructor, one for each dimension
}
};
The detail::enabler
enum is found at this almost-static-if link. Here it is used as a second parameter pack, allowing 0 arguments to be passed. The scoped enum has no members, and can't(?) be accidentally passed.
They also use a using
declaration to swallow some of the typename
etc parts up, but I've typed in full to avoid having to read it there.
How can I use the dimensions
parameter pack that I've passed?
The class works well, eg:
templateClass<2> temp(5, 2); // works
templateClass<3> temp(5, 2, 4); // works
templateClass<1> temp(5,2); // would give compile-time error
but perhaps I've gotten a (or several) bad idea(s) of what I should use/do here?
Edit:
One solution I've found is to create a std::initializer_list
. I can create this with an int
or size_t
class, which works nicely here. However, if I don't know the type of the arguments being passed (for example, because my function can take both int
s and double
s, for some other purpose), is there a better way than:
std::initializer_list<int> list{dimensions...};
for (int i : list) {
std::cout << "i = " << i << std::endl;
}
Full working example:
Mesh.H:
#ifndef MESH_H
#define MESH_H
#include <type_traits>
#include <initializer_list>
#include <iostream>
namespace detail {
enum class enabler {};
}
template <bool Condition>
using EnableIf =
typename std::enable_if<Condition, detail::enabler>::type;
template<size_t meshDim>
class Mesh
{
public:
template<class... DimArgs, EnableIf<sizeof...(DimArgs)==meshDim>...>
Mesh(DimArgs... dimensions){
std::initializer_list<int> list{dimensions...};
for (int i : list) {
std::cout << "i = " << i << std::endl;
}
}
};
#endif // MESH_H
main.cpp:
#include <iostream>
#include "Mesh.H"
int main()
{
Mesh<2> mesh(5, 2);
return 0;
}
Compiles with g++ --std=c++11 main.cpp