Why do I have to specialize recursive template variables? - c++

So I wrote an answer here: https://stackoverflow.com/a/56569397/2642059 which strives to compute log2 at compile time like so:
template <unsigned int x>
constexpr enable_if_t<x != 0U, int> log2 = 1 + log2<x / 2U>;
template <>
constexpr int log2<1U> = 0;
This works fine but I didn't feel like I should have had to specialize:
template <unsigned int x>
constexpr enable_if_t<x != 0U, int> log2 = x < 4U ? 1 : 1 + log2<x / 2U>;
But this gives me the error:
In substitution of template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = (0u != 0u); _Tp = int]:
prog.cpp:7:61: recursively required from constexpr std::enable_if_t<true, int> log2<4u>
prog.cpp:7:61: required from constexpr std::enable_if_t<true, int> log2<8u>
prog.cpp:10:11: required from here
/usr/include/c++/6/type_traits:2523:61: error: no type named type in struct std::enable_if<false, int>
Is there a way I can prevent the compiler from unrolling the recursion too far?

You use recursion to calculate log2. Each and every recursive operation in our life needs the leaf case.
In case of recursive leaf functions, the leaf case can be provided with non-recursive returns. However, with template variables the only way to provide the leaf case would be with specialization, there is no other way at all.
I believe, that you can achieve the very same goals with constexpr function and no TMP:
#include <type_traits>
constexpr int log2(int arg) {
if (arg == 0) return 0;
if (arg == 1) return 0;
return 1 + log2(arg / 2u);
}
constexpr std::integral_constant<int, log2(16)> z; // z.value == 4
This works with both run-time and compile-time arguments and generally should be preferred over pure TMP solution, except for educational purposes.
For educational or other undisclosed purposes, you can use exclusive compile-time like that:
#include <type_traits>
template<int arg>
constexpr int log2(std::integral_constant<int, arg> ) {
static_assert(arg > 0, "Bad arg to log2!");
if constexpr (arg == 1) {
return 0;
} else {
return 1 + log2(std::integral_constant<int, arg / 2> {});
}
}
int k = log2(std::integral_constant<int, 16>{});

Related

Constexpr typeid to order types [duplicate]

Consider the following program:
#include <tuple>
#include <vector>
#include <iostream>
#include <type_traits>
template <class T>
struct ordered {};
template <class... T>
struct ordered<std::tuple<T...>>
{
using type = /* a reordered tuple */;
};
template <class T>
using ordered_t = typename ordered<T>::type;
int main(int argc, char* argv[])
{
using type1 = std::tuple<char, std::vector<int>, double>;
using type2 = std::tuple<std::vector<int>, double, char>;
std::cout << std::is_same_v<type1, type2> << "\n"; // 0
std::cout << std::is_same_v<ordered_t<type1>, ordered_t<type2>> << "\n"; // 1
return 0;
}
The ordered helper has to reorder types in a tuple, such that two tuples with the sames types, but ordered differently lead to the same tuple type: which can be the first one, the second one, or even another one: it just has to have the same size, and the same elements but in a unique order (regardless of this order).
Is it possible to do this at compile-time using template metaprogramming techniques?
The hard part is coming up with a way to order types. Sorting a type list by a predicate is a chore, but is doable. I'll focus here on just the comparison predicate.
One way is to just create a class template that defines a unique id for each type. That works and makes for an easy comparator to write:
template <typename T, typename U>
constexpr bool cmp() { return unique_id_v<T> < unique_id_v<U>; }
But coming up with these unique ids is a hurdle that isn't necessarily feasible. Do you register them all in one file? That doesn't scale super well.
What would be great is if we could just... get the names of all the types as compile time strings. Reflection will give us that, and then this problem is trivial. Until then, we could do something slightly more dirty: use __PRETTY_FUNCTION__. Both gcc and clang are okay with using that macro in a constexpr context, although they have different formats for this string. If we have a signature like:
template <typename T, typename U>
constexpr bool cmp();
Then gcc reports cmp<char, int> as "constexpr bool cmp() [with T = char; U = int]" while clang reports it as "bool cmp() [T = char, U = int]". It's different... but close enough that we can use the same algorithm. Which is basically: figure out where T and U are in there and just do normal string lexicographic comparison:
constexpr size_t cstrlen(const char* p) {
size_t len = 0;
while (*p) {
++len;
++p;
}
return len;
}
template <typename T, typename U>
constexpr bool cmp() {
const char* pf = __PRETTY_FUNCTION__;
const char* a = pf +
#ifdef __clang__
cstrlen("bool cmp() [T = ")
#else
cstrlen("constexpr bool cmp() [with T = ")
#endif
;
const char* b = a + 1;
#ifdef __clang__
while (*b != ',') ++b;
#else
while (*b != ';') ++b;
#endif
size_t a_len = b - a;
b += cstrlen("; U = ");
const char* end = b + 1;
while (*end != ']') ++end;
size_t b_len = end - b;
for (size_t i = 0; i < std::min(a_len, b_len); ++i) {
if (a[i] != b[i]) return a[i] < b[i];
}
return a_len < b_len;
}
with some tests:
static_assert(cmp<char, int>());
static_assert(!cmp<int, char>());
static_assert(!cmp<int, int>());
static_assert(!cmp<char, char>());
static_assert(cmp<int, std::vector<int>>());
It's not the prettiest implementation, and I'm not sure it's meaningfully sanctioned by the standard, but it lets you write your sort without having to manually and carefully register all your types. And it compiles on clang and gcc. So maybe it's good enough.
This is a slight modification of the method presented by Barry, that works with Visual Studio. Instead of creating compile-time string that stores name of a function:
template <typename T, typename U>
constexpr bool cmp()
this method directly compares names of two types returned by type_name< T>::name(). Barry's method does not work when names of types T and U returned by macro __PRETTY_FUNCTION__ are separated by comma, since comma may also separate template arguments, when T or U are a class or function templates.
// length of null-terminated string
constexpr size_t cstrlen(const char* p)
{
size_t len = 0;
while (*p)
{
++len;
++p;
}
return len;
}
// constexpr string representing type name
template<class T>
struct type_name
{
static constexpr const char* name()
{
#if defined (_MSC_VER)
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
};
};
// comparison of types based on type names
template<class T1, class T2>
constexpr bool less()
{
const char* A = type_name<T1>::name();
const char* B = type_name<T2>::name();
size_t a_len = cstrlen(A);
size_t b_len = cstrlen(B);
size_t ab_len = (a_len < b_len) ? a_len : b_len;
for (size_t i = 0; i < ab_len; ++i)
{
if (A[i] != B[i])
return A[i] < B[i];
}
return a_len < b_len;
}
// simple checks
template<class ... Type>
struct list;
static_assert(less<list<int, void, list<void, int>>, list<int, void, list<void, void>>>());
static_assert(less<list<int, void, list<void, int>>, list<int, void, list<void, int>, int>>());
This method works on VS. I am not sure if it works on Clang or GCC.
tl;dr: Get the type name at compile-time, and order by that.
Previous answers are, in my opinion, a bit idiosyncratic - at least in implementation.
At this point we have a very nice, multi-compiler-supporting, function for obtaining a type's name as a compile-time string, as a string view. I'll only quote its signature here:
template <typename T>
constexpr std::string_view type_name();
This constitutes an injective mapping from types to compile-time-comparable values. Given those, you can easily implement a selection-sort-like procedure to get the relative order of each type. Finally, you assemble a new tuple using those orders.

How to order types at compile-time?

Consider the following program:
#include <tuple>
#include <vector>
#include <iostream>
#include <type_traits>
template <class T>
struct ordered {};
template <class... T>
struct ordered<std::tuple<T...>>
{
using type = /* a reordered tuple */;
};
template <class T>
using ordered_t = typename ordered<T>::type;
int main(int argc, char* argv[])
{
using type1 = std::tuple<char, std::vector<int>, double>;
using type2 = std::tuple<std::vector<int>, double, char>;
std::cout << std::is_same_v<type1, type2> << "\n"; // 0
std::cout << std::is_same_v<ordered_t<type1>, ordered_t<type2>> << "\n"; // 1
return 0;
}
The ordered helper has to reorder types in a tuple, such that two tuples with the sames types, but ordered differently lead to the same tuple type: which can be the first one, the second one, or even another one: it just has to have the same size, and the same elements but in a unique order (regardless of this order).
Is it possible to do this at compile-time using template metaprogramming techniques?
The hard part is coming up with a way to order types. Sorting a type list by a predicate is a chore, but is doable. I'll focus here on just the comparison predicate.
One way is to just create a class template that defines a unique id for each type. That works and makes for an easy comparator to write:
template <typename T, typename U>
constexpr bool cmp() { return unique_id_v<T> < unique_id_v<U>; }
But coming up with these unique ids is a hurdle that isn't necessarily feasible. Do you register them all in one file? That doesn't scale super well.
What would be great is if we could just... get the names of all the types as compile time strings. Reflection will give us that, and then this problem is trivial. Until then, we could do something slightly more dirty: use __PRETTY_FUNCTION__. Both gcc and clang are okay with using that macro in a constexpr context, although they have different formats for this string. If we have a signature like:
template <typename T, typename U>
constexpr bool cmp();
Then gcc reports cmp<char, int> as "constexpr bool cmp() [with T = char; U = int]" while clang reports it as "bool cmp() [T = char, U = int]". It's different... but close enough that we can use the same algorithm. Which is basically: figure out where T and U are in there and just do normal string lexicographic comparison:
constexpr size_t cstrlen(const char* p) {
size_t len = 0;
while (*p) {
++len;
++p;
}
return len;
}
template <typename T, typename U>
constexpr bool cmp() {
const char* pf = __PRETTY_FUNCTION__;
const char* a = pf +
#ifdef __clang__
cstrlen("bool cmp() [T = ")
#else
cstrlen("constexpr bool cmp() [with T = ")
#endif
;
const char* b = a + 1;
#ifdef __clang__
while (*b != ',') ++b;
#else
while (*b != ';') ++b;
#endif
size_t a_len = b - a;
b += cstrlen("; U = ");
const char* end = b + 1;
while (*end != ']') ++end;
size_t b_len = end - b;
for (size_t i = 0; i < std::min(a_len, b_len); ++i) {
if (a[i] != b[i]) return a[i] < b[i];
}
return a_len < b_len;
}
with some tests:
static_assert(cmp<char, int>());
static_assert(!cmp<int, char>());
static_assert(!cmp<int, int>());
static_assert(!cmp<char, char>());
static_assert(cmp<int, std::vector<int>>());
It's not the prettiest implementation, and I'm not sure it's meaningfully sanctioned by the standard, but it lets you write your sort without having to manually and carefully register all your types. And it compiles on clang and gcc. So maybe it's good enough.
This is a slight modification of the method presented by Barry, that works with Visual Studio. Instead of creating compile-time string that stores name of a function:
template <typename T, typename U>
constexpr bool cmp()
this method directly compares names of two types returned by type_name< T>::name(). Barry's method does not work when names of types T and U returned by macro __PRETTY_FUNCTION__ are separated by comma, since comma may also separate template arguments, when T or U are a class or function templates.
// length of null-terminated string
constexpr size_t cstrlen(const char* p)
{
size_t len = 0;
while (*p)
{
++len;
++p;
}
return len;
}
// constexpr string representing type name
template<class T>
struct type_name
{
static constexpr const char* name()
{
#if defined (_MSC_VER)
return __FUNCSIG__;
#else
return __PRETTY_FUNCTION__;
#endif
};
};
// comparison of types based on type names
template<class T1, class T2>
constexpr bool less()
{
const char* A = type_name<T1>::name();
const char* B = type_name<T2>::name();
size_t a_len = cstrlen(A);
size_t b_len = cstrlen(B);
size_t ab_len = (a_len < b_len) ? a_len : b_len;
for (size_t i = 0; i < ab_len; ++i)
{
if (A[i] != B[i])
return A[i] < B[i];
}
return a_len < b_len;
}
// simple checks
template<class ... Type>
struct list;
static_assert(less<list<int, void, list<void, int>>, list<int, void, list<void, void>>>());
static_assert(less<list<int, void, list<void, int>>, list<int, void, list<void, int>, int>>());
This method works on VS. I am not sure if it works on Clang or GCC.
tl;dr: Get the type name at compile-time, and order by that.
Previous answers are, in my opinion, a bit idiosyncratic - at least in implementation.
At this point we have a very nice, multi-compiler-supporting, function for obtaining a type's name as a compile-time string, as a string view. I'll only quote its signature here:
template <typename T>
constexpr std::string_view type_name();
This constitutes an injective mapping from types to compile-time-comparable values. Given those, you can easily implement a selection-sort-like procedure to get the relative order of each type. Finally, you assemble a new tuple using those orders.

expansion parameters pack (values) from template arguments

there is a trying to expand the pack using usual way with recursion:
template<bool first> int func1(int value = 0) {
return some_func(first, value);
}
template<bool first, bool... args> int func1(int value = 0) {
return func1<args...>(some_func(first, value) );
}
at the last step of compile time recursion, the call of func1 is ambiguous,
first candidate is a first function , it's clear , some concrete specialization in my case:
int func1(int) [with bool first = false]
but second one is
int func1(int) [with bool first = false; bool ...args = {}]
you see that is also correct - empty set of the arguments after first one.
any idea to prevent this ?
thank you
Disambiguate the base case from the recursive case by adding an explicit second parameter:
template<bool first> int func1(int value = 0) {
return some_func(first, value);
}
template<bool first, bool second, bool... args> int func1(int value = 0) {
return func1<second, args...>(some_func(first, value) );
}
Wandbox example
so the finally, I didn't use the recursion, but the only code below.
(actually std::array is not required but more useful from my perspective ,
the expanding can be archived by using C-like array too)
template <bool... args> unsigned long func1() {
std::array<bool, sizeof...(args)> ar{args...};
// the piece specific for my task
std::bitset<sizeof...(args)> bs;
for(std::size_t i = 0; i < ar.size(); ++i) {
bs[i] = ar[i];
}
// ... processing ...
return bs.to_ulong();
}

Partial class template specialization c++11

I am trying to compile the below code, but I am getting the error:
wrong number of template arguments
template<int start, int end, int step>
struct range{};
template<int start, int end>
struct range<start, end, 1>{};
template<int end>
struct range<0, end, 1>{};
int main() {
auto r1 = range<0, 5, 2>{};
auto r2 = range<5, 15>{}; //error: wrong number of template arguments
auto r3 = range<10>{}; //error: wrong number of template arguments
}
How can I create partial template class object?
If you want the ability to specify start before end, but also to have a default argument for start you could do something like this:
template <int... Args>
struct range {
static_assert(sizeof...(Args) > 0 && sizeof...(Args) <= 3,
"Must pass 1-3 args");
using ArgPack = std::tuple<std::integral_constant<int, Args>...>;
template <int Size, typename Then, typename Else>
using select_value = typename std::conditional_t<
(sizeof...(Args) > Size), Then, Else
>::type;
static constexpr int start = select_value<1,
std::tuple_element<0, ArgPack>, std::integral_constant<int,0>
>::value;
static constexpr int end = select_value<1,
std::tuple_element<1, ArgPack>, std::tuple_element<0, ArgPack>
>::value;
static constexpr int step = select_value<2,
std::tuple_element<2, ArgPack>, std::integral_constant<int,1>
>::value;
};
This has exactly the usage which you desire, like this:
int main()
{
using a = range<1,1,2>;
static_assert(a::start == 1 && a::end == 1 && a::step == 2, "wat");
using b = range<1,1>;
static_assert(b::start == 1 && b::end == 1 && b::step == 1, "wat");
using c = range<3>;
static_assert(c::start == 0 && c::end == 3 && c::step == 1, "wat");
}
Live Demo
You need to specify all the template arguments according to the primary template's declaration, then which one selected will be determined according to the template arguments.
auto r1 = range<0, 5, 2>{}; // the primary template
auto r2 = range<5, 15, 1>{}; // the 1st partial specified template
auto r3 = range<0, 10, 1>{}; // the 2nd partial specified template
If you want to specify fewer template arguments you might want default template arguments:
template<int end, int start = 0, int step = 1>
struct range{};
auto r1 = range<5, 0, 2>{}; // end->5, start->0, step->2
auto r2 = range<15, 5>{}; // end->15, start->5, step->1
auto r3 = range<10>{}; // end->10, start->0, step->1
Note that I changed the order of the template parameters, because if the default argument is specified for a template parameter, each subsequent template parameter must have a default argument too.

How to get the i-th element from an std::tuple when i isn't know at compile-time?

I have a variable i of type std::size_t and a tuple of type std::tuple. I want to get the i-th element of the tuple. I tried this:
// bindings... is of type const T&...
auto bindings_tuple = std::make_tuple(bindings...);
auto binding = std::tuple_element<i, const T&...>(bindings_tuple);
But I get this compile error saying that the first template argument must be an integral constant expression:
error: non-type template argument of type 'std::size_t' (aka 'unsigned long') is not an integral constant expression
Is it possible to get the i-th element of a tuple, and how to do that?
I would like to do this without using boost, if possible.
This is possible:
struct Functor
{
template<typename T>
void operator()(T& t) const { std::cout << t << std::endl; }
};
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
for_index(int, std::tuple<Tp...> &, FuncT)
{ }
template<std::size_t I = 0, typename FuncT, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
for_index(int index, std::tuple<Tp...>& t, FuncT f)
{
if (index == 0) f(std::get<I>(t));
for_index<I + 1, FuncT, Tp...>(index-1, t, f);
}
auto t = make_tuple(1, 2, "abc", "def", 4.0f);
int i = 2; // for example
for_index(i, t, Functor());
This code will print:
abc
Working sample on ideone: sample
You cannot. That's not what a tuple is for. If you need dynamic access to an element, use std::array<T,N>, which is almost identical to std::tuple<T,...,T> but gives you the dynamic [i]-operator; or even a fully dynamic container like std::vector<T>.
This is probably not what OP wants, but anyway, it is possible to return the i-th element using a run-time i provided you return a variant type such as boost::variant or boost::any,
#include <tuple>
#include <stdexcept>
#include <boost/variant.hpp>
template <size_t n, typename... T>
boost::variant<T...> dynamic_get_impl(size_t i, const std::tuple<T...>& tpl)
{
if (i == n)
return std::get<n>(tpl);
else if (n == sizeof...(T) - 1)
throw std::out_of_range("Tuple element out of range.");
else
return dynamic_get_impl<(n < sizeof...(T)-1 ? n+1 : 0)>(i, tpl);
}
template <typename... T>
boost::variant<T...> dynamic_get(size_t i, const std::tuple<T...>& tpl)
{
return dynamic_get_impl<0>(i, tpl);
}
For example:
#include <string>
#include <iostream>
int main()
{
std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
for (size_t i = 0; i < 5; ++ i)
std::cout << i << " = " << dynamic_get(i, tpl) << std::endl;
return 0;
}
will print:
0 = 4
1 = 6.6
2 = hello
3 = 7
terminate called after throwing an instance of 'std::out_of_range'
what(): Tuple element out of range.
Aborted
(The boost::variant<T...> requires g++ 4.7)
The question here, what would be the type return type if that would be possible? It has to be known at compile time, but tuple may contain elements of different types.
Let's assume we have a tuple of three elements:
auto tuple = std::make_tuple(10, "", A());
using tuple_type = decltype(tuple);
Apparently, getting N-th element doesn't make much sense. What type would it be? It's not known until runtime. However, rather than getting N-th element you can apply a function to it, given that all elements support some common protocol:
void process(int n)
{
if (n == 0)
func(std::get<0>(tuple));
else if (n == 1)
func(std::get<1>(tuple));
else if (n == 2)
func(std::get<2>(tuple));
}
This code "dynamically" processes element, given the index n. The common protocol in this example is function func which can do something meaningful with all possible types used in the tuple.
However, writing such code by hand is tedious, we want to make it more generic. Let's start with extracting the application function, so we can reuse same process function for different functors:
template<template<typename > class F>
void process(int n)
{
if (n == 0)
{
using E = typename std::tuple_element<0, tuple_type>::type;
F<E>::apply(std::get<0>(tuple));
}
else if (n == 1)
{
using E = typename std::tuple_element<1, tuple_type>::type;
F<E>::apply(std::get<1>(tuple));
}
else if (n == 2)
{
using E = typename std::tuple_element<2, tuple_type>::type;
F<E>::apply(std::get<2>(tuple));
}
}
In this case F could be implemented as something like:
// Prints any printable type to the stdout
struct printer
{
static void apply(E e)
{
std::cout << e << std::endl;
}
}
Let's make compiler to generate all of that code, let's make it generic:
constexpr static std::size_t arity = std::tuple_size<tuple_type>::value;
template<int N>
struct wrapper
{
template<template<typename, typename ... > class F>
static void apply_to(tuple_type& tuple, int idx)
{
if (idx)
// Double recursion: compile and runtime.
// Compile-time "recursion" will be terminated once
// we reach condition N == tuple arity
// Runtime recursion terminates once idx is zero.
wrapper<N + 1>::template apply_to<F>(tuple, idx - 1);
else
{
// idx == 0 (which means original index is equal to N).
using E = typename std::tuple_element<N, tuple_type>::type;
F<E>::apply(std::get<N>(tuple));
}
}
};
// Termination condition: N == arity.
template<>
struct wrapper<arity>
{
template<template<typename, typename ... > class F>
static void apply_to(tuple_type&, int)
{
// Throw exception or something. Index is too big.
}
};
Usage:
wrapper<0>::template apply_to<printer>(tuple, 2);
Making it completely generic is another story, though. At least it needs to be independent of the tuple type. Then, you probably want to generify return type of the functor, so you can return meaningful result. Third, making functor to accept extra parameters.
P.S. I am not real C++ developer, so the approach above could be total nonsence. However, I found it useful for my microcontroller project where I want as much as possible to be resolved at compile time and yet be generic enough, so I can shuffle things around easily. For example, a "menu" in my project is basically a tuple of "actions", there each action is a separate class which supports simple protocol like "print your label at current position on LCD" and "activate and run your UI loop".