Avoiding code duplication for runtime-to-compile-time numeric parameter translation - c++

Suppose we have function such as
template <typename T, unsigned N> void foo();
and for simplicity assume that we know that only (constant) values N_1, N_2 ... N_k are valid for N.
Now, suppose I want to make that compile-time parameter a run-time one, using foo() as a black-box, i.e. implement:
template <typename T> void foo(unsigned n);
by making foo<,>() calls. How should I go about doing that? Obviously, I can write:
template <typename T> void foo(unsigned n) {
switch(n) {
case N_1 : foo<T, N_1>(); break;
case N_2 : foo<T, N_2>(); break;
// etc. etc.
case N_k : foo<T, N_k>(); break;
}
}
... but this makes me feel all dirty. I could use a MAP() meta-macro to generate these k lines, I suppose; but can I do anything better and less-macroish to achieve the same? Is it possible to write something like the above that's general, and works for every variadic template and a fixed sequence of constant values?
Notes:
C++11/14/17-specific suggestions are obviously welcome.
The N's are not necessarily contiguous, nor small, nor sorted. e.g. suppose N_2 = 123456789 and N_5 = 1.

You could make a function pointer table:
using F = void(*)();
template <class T, class >
struct Table;
template <class T, size_t... Is>
struct Table<T, std::index_sequence<Is...> > {
static constexpr F fns[] = {
foo<T, Is>...
};
};
template <class T, size_t... Is>
constexpr F Table<T, std::index_sequence<Is...> >::fns[sizeof...(Is)];
And then just invoke the one you want:
template <class T, size_t N>
struct MakeTable : Table<T, std::make_index_sequence<N>> { };
template <typename T>
void foo(unsigned n) {
MakeTable<T, MaxN>::fns[n]();
}
If the N_ks aren't contiguous, then we can use a lambda for inline parameter unpacking:
template <class T>
void foo(unsigned n) {
using seq = std::index_sequence<N_1, N_2, ..., N_k>;
indexer(seq)([n](auto i){
if (n == i) {
f<T, i>();
}
});
}
If the above is too slow, then I guess just manually build a std::unordered_map<unsigned, void(*)()> or something.

In these kind of situations I like to build a static table of function pointers, with a dynamic parameter deciding which one to dispatch to. Below is an implementation that achieves this, in the function foo_dynamic. To this function, you specify the maximum value of N you'd like to support, and it builds a static table of function pointers using some recursive templates. You then dereference into this table with your dynamic parameter.
using ftype = void (*)();
template <typename T, unsigned N> void foo()
{
std::cout << N << std::endl;
}
template <typename T, unsigned max>
struct TablePopulator
{
static void populateFTable(ftype* table)
{
table[max] = foo<T,max>;
TablePopulator<T,max-1>::populateFTable(table);
}
};
template <typename T>
struct TablePopulator<T, 0>
{
static void populateFTable(ftype* table)
{
table[0] = foo<T,0>;
}
};
template<typename T, unsigned max_N>
std::array<ftype, max_N>& initTable()
{
static std::array<ftype, max_N> table;
TablePopulator<T, max_N-1>::populateFTable(table.data());
return table;
}
template<typename T, unsigned max_N>
void foo_dynamic(unsigned actualN)
{
static auto ftable = initTable<T, max_N>();
if(actualN >= max_N)
throw std::runtime_error("Max param exceeded");
ftable[actualN]();
}
int main()
{
foo_dynamic<int, 10>(1);
foo_dynamic<int, 10>(5);
return 0;
}
EDIT: Given the constraints in the question edit, here's an approach where valid indices are specified manually, which uses an unordered_map instead of an array:
using ftype = void (*)();
template <typename T, unsigned N> void foo()
{
std::cout << N << std::endl;
}
template<typename T, size_t ... Indices>
void foo_dynamic_indices(size_t actual_index)
{
static std::unordered_map<size_t, ftype> fmap = {{Indices, foo<T,Indices>}...};
auto fIt = fmap.find(actual_index);
if(fIt == fmap.end())
throw std::runtime_error("Index not found");
fIt->second();
}
int main()
{
foo_dynamic_indices<int, 0, 3, 400, 1021, 10000000>(10000000);
foo_dynamic_indices<int, 0, 3, 400, 1021, 10000000>(4); //Exception
return 0;
}

Related

A type trait to detect functors using C++17?

Problem description:
C++17 introduces std::invocable<F, Args...>, which is nice to detect if a type... is invocable with the given arguments. However, would there be a way to do it for any arguments for functors (because combinations of the existing traits of the standard library already allow to detect functions, function pointers, function references, member functions...)?
In other words, how to implement the following type trait?
template <class F>
struct is_functor {
static constexpr bool value = /*using F::operator() in derived class works*/;
};
Example of use:
#include <iostream>
#include <type_traits>
struct class0 {
void f();
void g();
};
struct class1 {
void f();
void g();
void operator()(int);
};
struct class2 {
void operator()(int);
void operator()(double);
void operator()(double, double) const noexcept;
};
struct class3 {
template <class... Args> constexpr int operator()(Args&&...);
template <class... Args> constexpr int operator()(Args&&...) const;
};
union union0 {
unsigned int x;
unsigned long long int y;
template <class... Args> constexpr int operator()(Args&&...);
template <class... Args> constexpr int operator()(Args&&...) const;
};
struct final_class final {
template <class... Args> constexpr int operator()(Args&&...);
template <class... Args> constexpr int operator()(Args&&...) const;
};
int main(int argc, char* argv[]) {
std::cout << is_functor<int>::value;
std::cout << is_functor<class0>::value;
std::cout << is_functor<class1>::value;
std::cout << is_functor<class2>::value;
std::cout << is_functor<class3>::value;
std::cout << is_functor<union0>::value;
std::cout << is_functor<final_class>::value << std::endl;
return 0;
}
should output 001111X. In an ideal world, X should be 1, but I don't think it's doable in C++17 (see bonus section).
Edit:
This post seems to present a strategy that solves the problem. However, would there be a better/more elegant way to do it in C++17?
Bonus:
And as a bonus, would there be a way to make it work on final types (but that's completely optional and probably not doable)?
Building on my answer to my answer to this qustion, i was able to solve your problem, including the bonus one :-)
The following is the code posted in the other thread plus some little tweaks to get a special value when an object can't be called. The code needs c++17, so currently no MSVC...
#include<utility>
constexpr size_t max_arity = 10;
struct variadic_t
{
};
struct not_callable_t
{
};
namespace detail
{
// it is templated, to be able to create a
// "sequence" of arbitrary_t's of given size and
// hece, to 'simulate' an arbitrary function signature.
template <size_t>
struct arbitrary_t
{
// this type casts implicitly to anything,
// thus, it can represent an arbitrary type.
template <typename T>
operator T&& ();
template <typename T>
operator T& ();
};
template <typename F, size_t... Is,
typename U = decltype(std::declval<F>()(arbitrary_t<Is>{}...))>
constexpr auto test_signature(std::index_sequence<Is...>)
{
return std::integral_constant<size_t, sizeof...(Is)>{};
}
template <size_t I, typename F>
constexpr auto arity_impl(int) -> decltype(test_signature<F>(std::make_index_sequence<I>{}))
{
return {};
}
template <size_t I, typename F, std::enable_if_t<(I == 0), int> = 0>
constexpr auto arity_impl(...) {
return not_callable_t{};
}
template <size_t I, typename F, std::enable_if_t<(I > 0), int> = 0>
constexpr auto arity_impl(...)
{
// try the int overload which will only work,
// if F takes I-1 arguments. Otherwise this
// overload will be selected and we'll try it
// with one element less.
return arity_impl<I - 1, F>(0);
}
template <typename F, size_t MaxArity = 10>
constexpr auto arity_impl()
{
// start checking function signatures with max_arity + 1 elements
constexpr auto tmp = arity_impl<MaxArity + 1, F>(0);
if constexpr(std::is_same_v<std::decay_t<decltype(tmp)>, not_callable_t>) {
return not_callable_t{};
}
else if constexpr (tmp == MaxArity + 1)
{
// if that works, F is considered variadic
return variadic_t{};
}
else
{
// if not, tmp will be the correct arity of F
return tmp;
}
}
}
template <typename F, size_t MaxArity = max_arity>
constexpr auto arity(F&& f) { return detail::arity_impl<std::decay_t<F>, MaxArity>(); }
template <typename F, size_t MaxArity = max_arity>
constexpr auto arity_v = detail::arity_impl<std::decay_t<F>, MaxArity>();
template <typename F, size_t MaxArity = max_arity>
constexpr bool is_variadic_v = std::is_same_v<std::decay_t<decltype(arity_v<F, MaxArity>)>, variadic_t>;
// HERE'S THE IS_FUNCTOR
template<typename T>
constexpr bool is_functor_v = !std::is_same_v<std::decay_t<decltype(arity_v<T>)>, not_callable_t>;
Given the classes in yout question, the following compiles sucessfully (you can even use variadic lambdas:
constexpr auto lambda_func = [](auto...){};
void test_is_functor() {
static_assert(!is_functor_v<int>);
static_assert(!is_functor_v<class0>);
static_assert(is_functor_v<class1>);
static_assert(is_functor_v<class2>);
static_assert(is_functor_v<class3>);
static_assert(is_functor_v<union0>);
static_assert(is_functor_v<final_class>);
static_assert(is_functor_v<decltype(lambda_func)>);
}
See also a running example here.

Make loop variable a constant in C++

I am currently creating arithmetic operators libraries for high level synthesis.
For this, I am also creating a library to manipulate bits and bit vectors like it would be done in VHDL. To make my libraries synthesizable, nearly everything must be resolved at compile time.
However, I have an issue with loops.
Indeed, I would like to be able to write things like that:
const int N = 5;
for(int i = 0; i < N-2; i++) {
x.bit<i+2>() = x.bit<i>();
}
Of course, it does not compile since i is a variable and not a constant determined at compile time.
However, N being a constant, this code is strictly equivalent to:
x.bit<2>() = x.bit<0>();
x.bit<3>() = x.bit<1>();
x.bit<4>() = x.bit<2>();
which compiles and works perfectly.
Is there a way to make the compiler (gcc in my case) unroll the loop since N is constant? Or to define a macro or a constexpr which could do it with a clean syntax? This would be the equivalent of for generate in VHDL.
While constexpr has got much more powerful in C++14/17 it is not yet possible to mix this kind of compile time / template code with an ordinary loop. There is some talk of introducing a construct that might enable that in a future version of C++. For now you have a few choices, either recursive calls to a function with an integer template argument or probably simpler in this case a C++17 fold expression. You could also use C++11 variadic template expansion to get a similar result to fold expressions in this example, though fold expressions are more powerful.
Just saw your comment about being stuck with C++11, you're probably better off using the recursive function approach I think. I've added that approach to the example.
If you were able to use C++14 you might also want to consider moving entirely into constexpr function / type land so your bit<I>() function would not be templated but would be just a constexpr function bit(i). You could then use normal functions and loops. Given the C++11 restrictions on constexpr functions that is probably less useful in your case however. I've added an example using that approach.
#include <iostream>
#include <utility>
template <size_t N>
struct bits {
bool bs[N];
template <size_t I>
constexpr const bool& bit() const {
return bs[I];
}
template <size_t I>
constexpr bool& bit() {
return bs[I];
}
constexpr bool bit(int i) const { return bs[i]; }
constexpr void bit(int i, bool x) { bs[i] = x; }
};
// Using C++17 fold expressions
template <size_t N, size_t... Is>
constexpr bits<N> set_bits_helper(bits<N> x, std::index_sequence<Is...>) {
((x.bit<Is + 2>() = x.bit<Is>()), ...);
return x;
}
template <size_t N>
constexpr bits<N> set_bits(bits<N> x) {
return set_bits_helper(x, std::make_index_sequence<N - 2>{});
}
// Using recursive template function, should work on C++11
template <size_t I, size_t N>
constexpr bits<N> set_bits_recursive_helper(bits<N> x, std::integral_constant<size_t, I>) {
x.bit<N - I>() = x.bit<N - I - 2>();
return set_bits_recursive_helper(x, std::integral_constant<size_t, I - 1>{});
}
template <size_t N>
constexpr bits<N> set_bits_recursive_helper(bits<N> x, std::integral_constant<size_t, 0>) { return x; }
template <size_t N>
constexpr bits<N> set_bits_recursive(bits<N> x) {
return set_bits_recursive_helper(x, std::integral_constant<size_t, N - 2>{});
}
// Using non template constexpr functions
template <size_t N>
constexpr bits<N> set_bits_constexpr(bits<N> x) {
for (int i = 0; i < N - 2; ++i) {
x.bit(i + 2, x.bit(i));
}
return x;
}
// Test code to show usage
template <size_t N>
void print_bits(const bits<N>& x) {
for (auto b : x.bs) {
std::cout << b << ", ";
}
std::cout << '\n';
}
void test_set_bits() {
constexpr bits<8> x{ 1, 0 };
print_bits(x);
constexpr auto y = set_bits(x);
static_assert(y.bit<2>() == x.bit<0>());
print_bits(y);
}
void test_set_bits_recursive() {
constexpr bits<8> x{ 1, 0 };
print_bits(x);
constexpr auto y = set_bits_recursive(x);
static_assert(y.bit<2>() == x.bit<0>());
print_bits(y);
}
void test_set_bits_constexpr() {
constexpr bits<8> x{ 1, 0 };
print_bits(x);
constexpr auto y = set_bits_constexpr(x);
static_assert(y.bit<2>() == x.bit<0>());
print_bits(y);
}
int main() {
test_set_bits();
test_set_bits_recursive();
test_set_bits_constexpr();
}
Also without std::integer_sequence (but I suggest to implement a substitute and use it), in C++11 you can use template partial specialization.
I mean that you can implement something like
template <int I, int Sh, int N>
struct shiftVal
{
template <typename T>
static int func (T & t)
{ return t.template bit<I+Sh>() = t.template bit<I>(),
shiftVal<I+1, Sh, N>::func(t); }
};
template <int I, int Sh>
struct shiftVal<I, Sh, I>
{
template <typename T>
static int func (T &)
{ return 0; }
};
and your cycle become
shiftVal<0, 2, N-2>::func(x);
The following is a full working example
#include <array>
#include <iostream>
template <std::size_t N>
struct foo
{
std::array<int, N> arr;
template <int I>
int & bit ()
{ return arr[I]; }
};
template <int I, int Sh, int N>
struct shiftVal
{
template <typename T>
static int func (T & t)
{ return t.template bit<I+Sh>() = t.template bit<I>(),
shiftVal<I+1, Sh, N>::func(t); }
};
template <int I, int Sh>
struct shiftVal<I, Sh, I>
{
template <typename T>
static int func (T &)
{ return 0; }
};
int main ()
{
foo<10U> f { { { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 } } };
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
shiftVal<0, 2, 10-2>::func(f);
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
Nobody else produce an example based on a C++11 simulation of std::integer_sequence (as suggested by W.F., Passer By and Sopel and the simpler solution, IMHO) so I propose the following one (of std::index_sequence and std::make_index_sequence in reality: simulate std::integer_sequence is more complicated)
template <std::size_t ...>
struct indexSequence
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSequenceHelper : public indexSequenceHelper<N-1U, N-1U, Next...>
{ };
template <std::size_t ... Next>
struct indexSequenceHelper<0U, Next ... >
{ using type = indexSequence<Next ... >; };
template <std::size_t N>
using makeIndexSequence = typename indexSequenceHelper<N>::type;
So a function (with function helper) to reproduce the asked loop can be written as
template
void shiftValHelper (T & t, indexSequence<Is...> const &)
{
using unused = int[];
(void)unused { 0,
(t.template bit<Is+Sh>() = t.template bit<Is>(), 0)... };
}
template <std::size_t Sh, std::size_t N, typename T>
void shiftVal (T & t)
{ shiftValHelper<Sh>(t, makeIndexSequence<N>{}); }
and called ad follows
shiftVal<2, N-2>(x);
The following is a full working example
#include <array>
#include <iostream>
template <std::size_t ...>
struct indexSequence
{ };
template <std::size_t N, std::size_t ... Next>
struct indexSequenceHelper : public indexSequenceHelper<N-1U, N-1U, Next...>
{ };
template <std::size_t ... Next>
struct indexSequenceHelper<0U, Next ... >
{ using type = indexSequence<Next ... >; };
template <std::size_t N>
using makeIndexSequence = typename indexSequenceHelper<N>::type;
template <std::size_t N>
struct foo
{
std::array<int, N> arr;
template <std::size_t I>
int & bit ()
{ return arr[I]; }
};
template <std::size_t Sh, typename T, std::size_t ... Is>
void shiftValHelper (T & t, indexSequence<Is...> const &)
{
using unused = int[];
(void)unused { 0,
(t.template bit<Is+Sh>() = t.template bit<Is>(), 0)... };
}
template <std::size_t Sh, std::size_t N, typename T>
void shiftVal (T & t)
{ shiftValHelper<Sh>(t, makeIndexSequence<N>{}); }
int main ()
{
foo<10U> f { { { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 } } };
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
shiftVal<2, 10-2>(f);
for ( auto const & i : f.arr )
std::cout << i << ' ';
std::cout << std::endl;
}

Sum Nested Template Parameters at Compile Time

I'm looking for a better way to calculate the sum of numeric template parameters associated with nested template classes. I have a working solution here, but I want to do this without having to create this extra helper template class DepthCalculator and partial specialization DepthCalculator<double,N>:
#include <array>
#include <iostream>
template<typename T,size_t N>
struct DepthCalculator
{
static constexpr size_t Calculate()
{
return N + T::Depth();
}
};
template<size_t N>
struct DepthCalculator<double,N>
{
static constexpr size_t Calculate()
{
return N;
}
};
template<typename T,size_t N>
class A
{
std::array<T,N> arr;
public:
static constexpr size_t Depth()
{
return DepthCalculator<T,N>::Calculate();
}
// ...
// Too many methods in A to write a separate specialization for.
};
int main()
{
using U = A<A<A<double,3>,4>,5>;
U x;
constexpr size_t Depth = U::Depth(); // 3 + 4 + 5 = 12
std::cout << "Depth is " << Depth << std::endl;
A<double,Depth> y;
// Do stuff with x and y
return 0;
}
The static function A::Depth() returns the proper depth at compile time, which can then be used as a parameter to create other instances of A. It just seems like a messy hack to have to create both the DepthCalculator template and a specialization just for this purpose.
I know I can also create a specialization of A itself with a different definition of Depth(), but this is even more messy due to the number of methods in A, most of which depend on the template parameters. Another alternative is to inherit from A and then specialize the child classes, but this also seems overly complicated for something that seems should be simpler.
Are there any cleaner solutions using C++11?
Summary Edit
In the end, this is the solution I went with in my working project:
#include <array>
#include <iostream>
template<typename T,size_t N>
class A
{
std::array<T,N> arr;
template<typename U>
struct Get { };
template<size_t M>
struct Get<A<double,M>> { static constexpr size_t Depth() { return M; } };
template<typename U,size_t M>
struct Get<A<U,M>>
{ static constexpr size_t Depth() { return M + Get<U>::Depth(); } };
public:
static constexpr size_t GetDepth()
{
return Get<A<T,N>>::Depth();
}
// ...
// Too many methods in A to write a separate specialization for.
};
int main()
{
using U = A<A<A<double,3>,4>,5>;
U x;
constexpr size_t Depth = U::GetDepth(); // 3 + 4 + 5 = 12
std::cout << "Depth is " << Depth << std::endl;
A<double,Depth> y;
// Do stuff with x and y
return 0;
}
Nir Friedman made some good points about why GetDepth() should be an external function, however in this case there are other Get functions (not shown) which are appropriately member functions, and therefore it would make the most sense to have GetDepth() a member function too. I also borrowed Nir's idea of having the Depth() functions only call themselves, rather than GetDepth() which creates a bit less circular dependencies.
I chose skypjack's answer because it most directly provided what I had originally asked for.
You said:
I want to do this without having to create this extra helper template class DepthCalculator
So, maybe this one (minimal, working example) is fine for you:
#include<type_traits>
#include<cassert>
template<class T, std::size_t N>
struct S {
template<class U, std::size_t M>
static constexpr
typename std::enable_if<not std::is_arithmetic<U>::value, std::size_t>::type
calc() {
return M+U::calc();
}
template<typename U, std::size_t M>
static constexpr
typename std::enable_if<std::is_arithmetic<U>::value, std::size_t>::type
calc() {
return M;
}
static constexpr std::size_t calc() {
return calc<T, N>();
}
};
int main() {
using U = S<S<S<double,3>,4>,5>;
static_assert(U::calc() == 12, "oops");
constexpr std::size_t d = U::calc();
assert(d == 12);
}
I'm not sure I got exactly your problem.
Hoping this can help.
If you are with C++14, you can use also:
template<class U, std::size_t M>
static constexpr
std::enable_if_t<not std::is_arithmetic<U>::value, std::size_t>
If you are with C++17, it becomes:
template<class U, std::size_t M>
static constexpr
std::enable_if_t<not std::is_arithmetic_v<U>, std::size_t>
The same applies to the other sfinaed return type.
Option #1
Redefine your trait as follows:
#include <array>
#include <cstddef>
template <typename T>
struct DepthCalculator
{
static constexpr std::size_t Calculate()
{
return 0;
}
};
template <template <typename, std::size_t> class C, typename T, std::size_t N>
struct DepthCalculator<C<T,N>>
{
static constexpr size_t Calculate()
{
return N + DepthCalculator<T>::Calculate();
}
};
template <typename T, std::size_t N>
class A
{
public:
static constexpr size_t Depth()
{
return DepthCalculator<A>::Calculate();
}
private:
std::array<T,N> arr;
};
DEMO
Option #2
Change the trait into function overloads:
#include <array>
#include <cstddef>
namespace DepthCalculator
{
template <typename T> struct tag {};
template <template <typename, std::size_t> class C, typename T, std::size_t N>
static constexpr size_t Compute(tag<C<T,N>>)
{
return N + Compute(tag<T>{});
}
template <typename T>
static constexpr size_t Compute(tag<T>)
{
return 0;
}
}
template <typename T, std::size_t N>
class A
{
public:
static constexpr std::size_t Depth()
{
return Compute(DepthCalculator::tag<A>{});
}
private:
std::array<T,N> arr;
};
DEMO 2
You can do this wholly non-intrusively, which I think is advantageous:
template <class T>
struct Depth
{
constexpr static std::size_t Calculate()
{
return 0;
}
};
template <class T, std::size_t N>
struct Depth<A<T, N>>
{
constexpr static std::size_t Calculate()
{
return N + Depth<T>::Calculate();
}
};
Usage:
using U = A<A<A<double,3>,4>,5>;
constexpr size_t depth = Depth<U>::Calculate(); // 3 + 4 + 5 = 12
I realize your original question was how to do this without the extra "helper template", which my solution still has. But on the flip side, it's moved the functionality completely out of A itself, so its not really a helper template any more, it's just a template. This is pretty short, doesn't have any template template parameters unlike Piotr's solutions, is easy to extend with other classes, etc.

How to work around partial specialization of function template?

For example, I have a class:
class A
{
enum {N = 5};
double mVariable;
template<class T, int i>
void f(T& t)
{
g(mVariable); // call some function using mVariable.
f<T, i+1>(t); // go to next loop
}
template<class T>
void f<T, N>(T& t)
{} // stop loop when hit N.
};
Partial specialization is not allowed in function template. How do I work around it in my case?
I slightly changed the example of Arne Mertz, like:
template<int n>
struct A
{
enum {N = n};
...
};
and use A like:
A<5> a;
The I cannot compile on Visual Studio 2012. Is it a compiler bug or something else? It is quite strange.
EDIT: Checked. It is a Visual Studio bug. :(
I think Nim gives the most simple way to implement it.
The most straight forward solution is to use a template class instead of a function:
class A
{
enum {N = 5};
double mVariable;
template <class T, int i>
struct fImpl {
static_assert(i<N, "i must be equal to or less than N!");
static void call(T& t, A& a) {
g(a.mVariable);
fImpl<T, i+1>::call(t, a);
}
};
template<class T>
struct fImpl<T,N> {
static void call(T&, A&) {} // stop loop when hit N.
};
public:
template<class T, int i>
void f(T& t)
{
fImpl<T, i>::call(t,*this);
}
};
Example link
You can define a helper class:
template <int i, int M>
struct inc_up_to
{
static const int value = i + 1;
};
template <int i>
struct inc_up_to<i, i>
{
static const int value = i;
};
template<class T, int i>
void f(T& t)
{
if (i < N) {
g(mVariable); // call some function using mVariable.
f<T, inc_up_to<i, N>::value>(t);
}
}
It stops the compile-time recursion by making f<T, N> refer to f<T, N>, but that call is avoided by the run-time condition, breaking the loop.
A simplified and more robust version of the helper (thanks #ArneMertz) is also possible:
template <int i, int M>
struct inc_up_to
{
static const int value = (i >= M ? M : i + 1); // this caps at M
// or this:
static const int value = (i >= M ? i : i + 1); // this leaves i >= M unaffected
};
This doesn't even need the partial specialisation.
With c++11 support, you can do the following:
#include <iostream>
#include <type_traits>
using namespace std;
struct A
{
enum {N = 5};
double mVariable;
void g(int i, double v)
{ std::cout << i << " " << v << std::endl; }
template<int i, class T>
typename enable_if<i >= N>::type f(T& t)
{} // stop loop when hit N.
template<int i, class T>
typename enable_if<i < N>::type f(T& t)
{
g(i, mVariable); // call some function using mVariable.
f<i+1, T>(t); // go to next loop
}
};
int main(void)
{
A a;
int v = 0;
a.f<0>(v);
}
Main reason I like is that you don't need any of the cruft as required by the previous answers...
You can emulate partial specialization of function template with function overloading:
#include <type_traits>
class A
{
enum {N = 5};
double mVariable;
// ...
void g(double)
{
// ...
}
public:
template<class T, int i = 0>
void f(T& t, std::integral_constant<int, i> = std::integral_constant<int, i>())
{
g(mVariable);
f(t, std::integral_constant<int, i + 1>());
}
template<class T>
void f(T& t, std::integral_constant<int, N>)
{
}
};
Example of using:
A a;
int t = 0;
a.f(t);
a.f(t, std::integral_constant<int, 2>()); // if you want to start loop from 2, not from 0
It is a C++11 solution, however (not so much because of std::integral_constant class, but because of default template parameter of function template). It can be made shorter using some additional C++11 features:
template<int i>
using integer = std::integral_constant<int, i>;
template<class T, int i = 0>
void f(T& t, integer<i> = {})
{
g(mVariable);
f(t, integer<i + 1>());
}
template<class T>
void f(T& t, integer<N>)
{
}

A workaround for partial specialization of function template?

Consider the following metafunction for an integral pow (it is just an example) :
class Meta
{
template<int N, typename T> static constexpr T ipow(T x)
{
return (N > 0) ? (x*ipow<N-1>(x))
: ((N < 0) ? (static_cast<T>(1)/ipow<N>(x))
: (1))
}
};
How to write the stop condition for such a function ?
Anytime you ask yourself "how to simulate partial specialization for functions", you can think "overload, and let partial ordering decide what overload is more specialized".
template<int N>
using int_ = std::integral_constant<int, N>;
class Meta
{
template<int N, typename T> static constexpr T ipow(T x)
{
return ipow<N, T>(x, int_<(N < 0) ? -1 : N>());
}
template<int N, typename T> static constexpr T ipow(T x, int_<-1>)
{
// (-N) ??
return static_cast<T>(1) / ipow<-N>(x, int_<-N>());
}
template<int N, typename T> static constexpr T ipow(T x, int_<N>)
{
return x * ipow<N-1>(x, int_<N-1>());
}
template<int N, typename T> static constexpr T ipow(T x, int_<0>)
{
return 1;
}
};
I think you wanted to pass -N instead of N at the comment-marked position.
A simple version might go like this:
template <typename T, unsigned int N> struct pow_class
{
static constexpr T power(T n) { return n * pow_class<T, N - 1>::power(n); }
};
template <typename T> struct pow_class<T, 0>
{
static constexpr T power(T) { return 1; }
};
template <unsigned int N, typename T> constexpr T static_power(T n)
{
return pow_class<T, N>::power(n);
}
Usage:
auto p = static_power<5>(2); // 32
Just use static members in a class template and specialize the class template. You might want to create a forwarding function template for convenience, though.