Variadic templates with constants - c++

I'm doing some experimenting with metaprogramming and variadic templates, and I'm having trouble with some confusing behaviour. I've stripped it down to a minimum working example, but essentially I want to keep track of how many recursive calls I'm making. I want to do this by making the first template parameter an integer, while the second template parameter is a variadic list. In simplest form it looks like this:
template<typename... List>
struct initial_call{
static const int val = next_call<0, List...>::val;
};
template<int D, typename... List>
struct next_call {
static const int val = D;
};
So ignoring the fact that this code is pointless, it doesn't compile on VS2013, claiming "unexpected type 'List", on the line inside the definition of initial_call. Without the integer in front, it works fine. So is there a way to combine variadic templates with integer template parameters?

You might want something like this (counting the number of types):
#include <iostream>
// More than one type: Increment size and consume.
template<size_t N, typename T, typename... List>
struct calculate_list_size {
static const size_t value = calculate_list_size<N + 1, List...>::value;
};
// Last type: Increment size and terminate.
template<size_t N, typename T>
struct calculate_list_size<N, T> {
static const size_t value = N + 1;
};
// Forward to calculate_list_size.
template<typename... List>
struct list_size {
static const size_t value = calculate_list_size<0, List...>::value;
};
// Empty list
template<>
struct list_size<> {
static const size_t value = 0;
};
int main()
{
std::cout << list_size<char, short, int>::value << '\n';
std::cout << list_size<>::value << '\n';
}

Related

How pass the same struct with different template argument as parameter pack

Thanks to SO guys I resolved one of my problem:
Create a tuple with variatic type wrapped
But I realized after that, I still have a problem that I can't solve.
So now I have :
template < typename T,
size_t Size >
struct Metadata {
using type = T;
std::bitset<Size> bitset;
};
template <class... Ts>
constexpr auto make_metadata()
{
constexpr size_t N = sizeof...(Ts);
return std::make_tuple(Metadata<Ts, N>{0}...);
}
I intent to use it "like" that :
constexpr auto result = make_metadata<Foo1, Foo2, Foo3>({0}, {0}, {0});
And according to Jarod42 comment, I think I'll need 2 functions.
But how I can pass the arguments to the function and then to the tuple?
And I wonder how do that but without force to pass each arguments for each Ts, if they are not present I'll just put a default value (2 questions).
this may be what you want, I am not sure. (since you never show where the arguments to be used)
#include <tuple>
#include <bitset>
#include <iostream>
struct A{int value;};
struct B{int value;};
struct C{int value;};
template <typename T,int Size>
struct Metadata{
using type = T;
T value;
std::bitset<Size> bitset;
};
template <typename...Ts,typename...Args>
constexpr auto make_metadata(Args... args)
{
constexpr auto N = sizeof...(Ts);
return std::make_tuple(Metadata<Ts, N>{args,0}...);
}
int main(){
auto data = make_metadata<A,B,C>(1,2,3);
std::cout << "(" << std::get<0>(data).value.value
<< ", " << std::get<1>(data).value.value
<< ", " << std::get<2>(data).value.value << ")";
}

Infinite recursion in templates

Suppose I have a proxy class called List which is nothing more than a holder for a bunch of typenames:
template<typename... items> class List {
constexpr size_t SizeOf = /*Magic code that determines the length*/;
};
And suppose I have another class which is supposed to take to Lists and output a version where the smaller one is padded with null_ts:
template<class flist,class slist>
class Pad{
typedef /*Undertermined*/ Flist;
typedef /*Undertermined*/ Slist;
};
The only real problem is breaking the recursion....normally in template recursion you just specialize and then you can end it.
Here is a little different because there is no way (at least that I can see) to tell by the template deceleration the difference between the two list.
I tried to use a std::conditional to end the cycle but that does not work.
Here is an example:
template<int x>
class Mine{
typedef std::conditional<x == 12, Mine<x>::value, Mine<x+1>::value> value;
};
Even though I have the x==12 condition it still needs (or wants) to flush out the Mine<x+1>::value.
So what is the general strategy for this scenario?
This is a non-recursive solution for the implementation of Pad, but it also shows how you can use partial specialization to avoid instantiating templates based on a condition:
#include <cstddef>
#include <utility>
#include <type_traits>
#include <iostream>
template<class... Ts> struct List { static constexpr std::size_t size = sizeof...(Ts); };
struct null_t { };
template<std::size_t> using make_null_t = null_t;
template<class, class> struct pad_imp2;
template<class... Ts, std::size_t... Is> struct pad_imp2<List<Ts...>, std::index_sequence<Is...>>
{
using type = List<Ts..., make_null_t<Is>...>;
};
// Don't instantiate make_index_sequence if L::size >= S.
template<class, std::size_t, bool> struct pad_imp { using type = void; };
template<class L, std::size_t S> struct pad_imp<L, S, true>
{
using type = typename pad_imp2<L, std::make_index_sequence<S - L::size>>::type;
};
template<class L, std::size_t S> using pad_hlp = typename pad_imp<L, S, L::size < S>::type;
template<class L1, class L2> struct Pad
{
using L1_padded = std::conditional_t<L1::size < L2::size, pad_hlp<L1, L2::size>, L1>;
using L2_padded = std::conditional_t<L2::size < L1::size, pad_hlp<L2, L1::size>, L2>;
};
int main()
{
using list1 = List<short, int, long>;
using list2 = List<double>;
std::cout << std::is_same<Pad<list1, list2>::L1_padded, list1>::value << '\n';
std::cout << std::is_same<Pad<list1, list2>::L2_padded, List<double, null_t, null_t>>::value << '\n';
}
The padding is done by generating a list of null_ts using the dummy make_null_t alias template and a pack of indices of the right size.
One way to stop the recursion in your second example is to use boost.mpl. For example,
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/integral_c.hpp>
template<int x>
struct Mine {
using type = typename boost::mpl::eval_if<boost::mpl::bool_<x == 12>,
boost::mpl::integral_c<short, 12>,
Mine<x+1>
>::type;
};
In the above example, it will always give you 12 as a value, regardless of the argument (as long as it is less or equal to 12).
As I understood you need to break recursion at Mine structure. If that is right, you can use full template specialization of this struct (for implementing terminal case of recursion). It looks like that:
template<>
struct Mine<123456>{
// It is struct represents end of recursion
};
It is simple example of usage this approach for computing factorial:
#include <iostream>
template <int N>
struct Factorial
{
static const int fact = N * Factorial<N - 1>::fact;
};
template <>
struct Factorial<0>
{
static const int fact = 1;
};
int main()
{
std::cout << Factorial<1>::fact << std::endl;
std::cout << Factorial<3>::fact << std::endl;
return 0;
}

Associating an array with a variadic template

I'm now learning a little about templates and templates in C++11, C++14 and C++1z. I'm trying to write a variadic class template with an inside class that will associate an int to every template argument - and have a constexpr method that returns its array representation.
Let's say that I have ensured that the template cannot receive two of the same type as an argument. I was thinking about doing it somewhat like this:
template <typename... Types>
struct MyVariadicTemplate {
//we know that all types in Types... are different
template <int... Values>
struct MyInnerTemplate {
//I need to make sure that sizeof...(Values) == sizeof...(Types)
constexpr std::array<int, sizeof...(Values)> to_array() {
std::array<int, sizeof...(Values)> result = {Values...};
return result;
// this is only valid since C++14, as far as I know
}
};
};
this code should be valid (if it's not, I'd love to know why). Now, I'd like to add another inner template:
template <typedef Type>
struct AnotherInnerTemplate {};
that has a public typedef, which represents MyInnerTemplate with one on the position of Type in Types... and zeros elsewhere - and here I'm lost. I don't know how to proceed
I would appreciate any hint on how that can be done - and if I'm heading towards the wrong direction, I hope somebody can give me a hint on how to do that.
I think what you're looking for is something like this.
#include <array>
#include <cstddef>
#include <iostream>
#include <type_traits>
template <typename NeedleT, typename... HaystackTs>
constexpr auto get_type_index_mask() noexcept
{
constexpr auto N = sizeof...(HaystackTs);
return std::array<bool, N> {
(std::is_same<NeedleT, HaystackTs>::value)...
};
}
template <typename T, std::size_t N>
constexpr std::size_t ffs(const std::array<T, N>& array) noexcept
{
for (auto i = std::size_t {}; i < N; ++i)
{
if (array[i])
return i;
}
return N;
}
int
main()
{
const auto mask = get_type_index_mask<float, bool, int, float, double, char>();
for (const auto& bit : mask)
std::cout << bit;
std::cout << "\n";
std::cout << "float has index " << ffs(mask) << "\n";
}
Output:
00100
float has index 2
The magic happens in the parameter pack expansion
(std::is_same<NeedleT, HaystackTs>::value)...
where you test each type in HaystackTs against NeedleT. You might want to apply std::decay to either type if you want to consider, say, const int and int the same type.
template <int size, int... Values> struct AnotherImpl {
using Type = typename AnotherImpl<size - 1, Values..., 0>::Type;
};
template <int... Values> struct AnotherImpl<0, Values...> {
using Type = Inner<Values...>;
};
template <class T> struct Another {
using Type = typename AnotherImpl<sizeof...(Types) - 1, 1>::Type;
};
Full:
template <class... Types> struct My {
template <int... Values> struct Inner {
constexpr std::array<int, sizeof...(Values)> to_array() {
return std::array<int, sizeof...(Values)>{Values...};
}
};
template <int size, int... Values> struct AnotherImpl {
using Type = typename AnotherImpl<size - 1, Values..., 0>::Type;
};
template <int... Values> struct AnotherImpl<0, Values...> {
using Type = Inner<Values...>;
};
template <class T> struct Another {
using Type = typename AnotherImpl<sizeof...(Types) - 1, 1>::Type;
};
};
auto main() -> int {
My<int, float, char>::Another<int>::Type s;
auto a = s.to_array();
for (auto e : a) {
cout << e << " ";
}
cout << endl;
return 0;
}
prints:
1 0 0
Is this what you want?

Initialise static const int with static function

I have a template class with some integers as arguments. One static const integer (call it Length) of this class needs to be calculated based on the arguments. The calculation does need a loop (as far as I know) so a simple expression won't help.
static int setLength()
{
int length = 1;
while (length <= someTemplateArgument)
{
length = length << 1;
}
return length;
}
The returned length should be used to init Length. Lengthis used as a fixed length of an array so I need it to be constant.
Is there a solution for this issue? I know that constexp could help but I can't use C11 or later.
Using metaprogramming. Implementation of C++11 enable_if taken from cppreference.com
#include <iostream>
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
template <int length, int arg, typename = void>
struct length_impl
{
static const int value = length_impl<(length << 1), arg>::value;
};
template <int length, int arg>
struct length_impl<length, arg, typename enable_if<(length > arg)>::type>
{
static const int value = length ;
};
template <int arg>
struct length_holder
{
static const int value = length_impl<1, arg>::value;
};
template<int n>
struct constexpr_checker
{
static const int value = n;
};
int main()
{
std::cout << constexpr_checker< length_holder<20>::value >::value;
}

How to get value of integer template parameter?

title might be confusing, but lets say I have a template:
template <typename T, size_t offset>
struct offsetedIdxArray
{
//...
}
And after I create an instance:
static const size_t offset(1701);
offsetedIdxArray<zmq::socket_t, offset> oia;
Is there a way to get offset variable from oia. I know I can just use offset but from code style perspective i prefer to get it from oia if possible.
EDIT: I'm looking for a way to get offset without helper variable inside struct...
If you want to obtain the information from an offsetedIdxArray<T,N> object without adding any members to the class template, you can use a template function:
#include <iostream>
#include <cstddef>
template <typename T, size_t offset>
struct offsetedIdxArray
{
};
template <typename T, size_t offset>
size_t getOffset(const offsetedIdxArray<T, offset>&) {
return offset;
}
int main()
{
offsetedIdxArray<int,5> oia;
std::cout << getOffset(oia) << "\n";
}
Otherwise you can add a static constant or enum data member, as suggested in other posts.
template <typename T, size_t offset>
struct offsetedIdxArray
{
static const size_t off = offset;
//...
};
and get the variable off.