Related
I'm trying to use enum types to indexig some array but I want to allow different ordering of the vector depending on some option. In the class I also want functions that take the enum variable as input and use it as it should.
The solution I found is the following
#include<iostream>
#include<array>
#include<vector>
struct A{
struct XYZ{
enum coord{X=0,Y,Z};
};
struct YZX{
enum coord{Y=0,Z,X};
};
struct ZXY{
enum coord{Z=0,X,Y};
};
std::array<std::vector<float>,3> val;
void resize(int opt, size_t dim){
val[opt].resize(dim);
return;
}
void printsize(){
for(auto & i : val){
std::cout << i.size() << " ";
}
std::cout << std::endl;
return;
}
};
int main(){
A foo1;
A foo2;
A foo3;
foo1.resize(XYZ::X,10);
foo2.resize(YZX::X,10);
foo3.resize(ZXY::X,10);
std::cout << "Size foo1\n";
foo1.printsize();
std::cout << "Size foo2\n";
foo2.printsize();
std::cout << "Size foo3\n";
foo3.printsize();
return 0;
}
What I don't like in this solution is that my function resize takes an integer type as input and there's no type control of the enum.
Is there any other smarter solution? Am I doing something considered as anti-pattern?
Thank you
I suggest you to modify the member function resize (three parameters instead of two) and exploit the type safety of the enum classes:
#include <stdio.h>
#include<iostream>
#include<array>
#include<vector>
struct A{
enum class Coordinate
{
X = 0,
Y = 1,
Z = 2
};
enum class Permutation
{
XYZ = 0,
ZXY = 1,
YZX = 2
};
std::array<std::vector<float>,3> val;
/* resize takes three parameters now */
void resize(Permutation p, Coordinate c, size_t dim)
{
int index = ( static_cast<int>(p) + static_cast<int>(c) ) % 3 ;
val[index].resize(dim);
return;
}
void printsize(){
for(auto & i : val){
std::cout << i.size() << " ";
}
std::cout << std::endl;
return;
}
};
int main()
{
A foo1;
A foo2;
A foo3;
foo1.resize(A::Permutation::XYZ, A::Coordinate::X,10);
foo2.resize(A::Permutation::YZX, A::Coordinate::X,10);
foo3.resize(A::Permutation::ZXY, A::Coordinate::X,10);
std::cout << "Size foo1\n";
foo1.printsize();
std::cout << "Size foo2\n";
foo2.printsize();
std::cout << "Size foo3\n";
foo3.printsize();
return 0;
}
How about an Index class, constructible from several enum classes?
struct A
{
enum class XYZ {X,Y,Z};
enum class YZX {Y,Z,X};
enum class ZXY {Z,X,Y};
struct Index
{
int value;
operator int() const {return value;}
Index(XYZ value) : value(int(value)) {}
Index(YZX value) : value(int(value)) {}
Index(ZXY value) : value(int(value)) {}
};
std::array<std::vector<float>, 3> val;
void resize(Index opt, size_t dim)
{
val[opt].resize(dim);
}
void printsize() const
{
for (const auto &i : val)
std::cout << i.size() << ' ';
std::cout << '\n';
}
};
following from this question, I have been trying to create a template function that calls all same-named methods of its mixins. This has been done and verified in the previous question.
Now I am attempting to get the return value of SensorType::
Analytically:
#include<iostream>
#include <string>
struct EdgeSensor
{
void update(int i) { std::cout << "EdgeSensor::update " << i << std::endl; }
void updat2(const int i ) { std::cout << "EdgeSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "EdgeSensor::printStats" << std::endl;
return std::string("EdgeSensor::printStats"); }
};
struct TrendSensor
{
void update(int i ) { std::cout << "TrendSensor::update" << i << std::endl; }
void updat2(const int i ) { std::cout << "TrendSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "TrendSensor::printStats" << std::endl;
return std::string("TrendSensor::printStats"); }
};
template <class T, void (T::*)(const int)>
struct Method { };
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
template <class T, void(T::*M)(const int)>
int runSingle(Method<T, M> , const int i) {
(this->*M)(i);
return 0;
}
template <class... Ts>
void runAll(const int i) {
int run[sizeof...(Ts)] = { runSingle(Ts{},i)... };
(void)run;
}
public:
void update() {
runAll<Method<SensorType, &SensorType::update>...>(2);
}
void updat2() {
const int k = 3;
runAll<Method<SensorType, &SensorType::updat2>...>(k);
}
void printStats() {
// runAll<Method<SensorType, &SensorType::printStats>...>();
}
};
int main() {
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
}
The above compiles and runs fine. The problem is: how can I gather the return values (std::strings) from running the mixin SensorType::printStats() methods in BaseSensor::printStats() ?
If I try to create a 2ndary version of the run* functions and the Method template, I fail to make it compile. Say I did:
template <class T, void (T::*)()>
struct Method2 { };
template <class T, void(T::*M)()>
int runSingle2(Method2<T, M>) {
(this->*M)();
return 0;
}
template <class... Ts>
void runAll2() {
std::string s;
int run[sizeof...(Ts)] = { s = runSingle2(Ts{})... };
(void)run;
std::cout << "s=" << s << std::endl;
}
public:
void update() {
int k = 4;
runAll<Method<SensorType, &SensorType::update>...>(k);
}
void printStats() {
runAll2<Method2<SensorType, &SensorType::printStats>...>();
}
};
This does not compile saying
g++ -Wall -Wextra -g -std=c++11 -c -o "obj_dbg/main.opp" "main.cpp"
main.cpp: In instantiation of ‘void BaseSensor<SensorType>::printStats() [with SensorType = EdgeSensor, TrendSensor]’:
main.cpp:65:20: required from here
main.cpp:58:8: error: could not convert template argument ‘&EdgeSensor::printStats’ to ‘void (EdgeSensor::*)()’
make: *** [obj_dbg/main.opp] Error 1
So HOW can I grab the return values from SensorType::printStats()?
Not sure if you can use c++11, if so, then I think this is the easiest?
#include <iostream>
#include <string>
struct EdgeSensor
{
void update(int i) { std::cout << "EdgeSensor::update " << i << std::endl; }
void updat2(const int i ) { std::cout << "EdgeSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "EdgeSensor::printStats" << std::endl;
return std::string("EdgeSensor::printStats"); }
};
struct TrendSensor
{
void update(int i ) { std::cout << "TrendSensor::update" << i << std::endl; }
void updat2(const int i ) { std::cout << "TrendSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "TrendSensor::printStats" << std::endl;
return std::string("TrendSensor::printStats"); }
};
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
public:
void update() {
auto v = { (static_cast<SensorType*>(this)->update(1), 0)... }; // *
(void) v;
}
void updat2() {
const int k = 3;
auto v = { (static_cast<SensorType*>(this)->updat2(k), 0)... }; // *
(void) v;
}
void printStats() {
auto v = { static_cast<SensorType*>(this)->printStats()... };
for (auto s : v) {
std::cout << s << std::endl;
}
}
};
int main() {
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
}
NOTE: I am using a gcc extension here, but I think you are using gcc, so it should be okay
Here is you code reviewed so as it works as requested:
#include<iostream>
#include <string>
#include <vector>
struct EdgeSensor
{
void update(int i) { std::cout << "EdgeSensor::update " << i << std::endl; }
void updat2(const int i ) { std::cout << "EdgeSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "EdgeSensor::printStats" << std::endl;
return std::string("EdgeSensor::printStats"); }
};
struct TrendSensor
{
void update(int i ) { std::cout << "TrendSensor::update" << i << std::endl; }
void updat2(const int i ) { std::cout << "TrendSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "TrendSensor::printStats" << std::endl;
return std::string("TrendSensor::printStats"); }
};
template<typename ... SensorType>
class BaseSensor : public SensorType ... {
template<typename F>
struct Invoke;
template<typename R, typename... A>
struct Invoke<R(A...)> {
template <R(SensorType::* ...M)(A...), typename T>
static std::vector<R> run(T *t, A... args) {
std::vector<R> vec;
int arr[] = { (vec.push_back((t->*M)(args...)), 0)... };
(void)arr;
return vec;
}
};
template<typename... A>
struct Invoke<void(A...)> {
template <void(SensorType::* ...M)(A...), typename T>
static void run(T *t, A... args) {
int arr[] = { ((t->*M)(args...), 0)... };
(void)arr;
}
};
public:
void update() {
Invoke<void(int)>::template run<&SensorType::update...>(this, 2);
}
void updat2() {
const int k = 3;
Invoke<void(int)>::template run<&SensorType::updat2...>(this, k);
}
void printStats() {
auto vec = Invoke<std::string(void)>::template run<&SensorType::printStats...>(this);
for(auto &&v: vec) {
std::cout << "--->" << v << std::endl;
}
}
};
int main() {
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
}
I refactored a bit the code, for there was no need for the Method class. This works as intended and the strings returned by the printStats methods are now collected in a std::vector and returned to the caller.
To extend the solution to any type of member function you could do (and actually a bit simplify it still having in mind c++11 restriction). The approach resolves type of member function to be able to infer its result type. It also uses InferOwnerType to infer mixin type and avoid direct passing of statically casted this pointer. Depending on the result of the member function now we can store it into an array or use the trick with int array just to be sure each member function is invoked.
#include <iostream> // std::cout std::endl
#include <string> // std::string
#include <utility> // std::declval
struct EdgeSensor //a mixin
{
void update(int a){ std::cout << "EdgeSensor::update" << a << std::endl; }
std::string updat2(int const v) { return "EdgeSensor::printStats"; }
};
struct TrendSensor //another mixin
{
void update(int a){ std::cout << "TrendSensor::update" << std::endl; }
std::string updat2(int const v) { return "TrendSensor::printStats"; }
};
template <class Res, class This, class... Args>
This InferOwnerType(Res (This::*foo)(Args...)) { }
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
template <class M, class... Args>
auto run(M m, Args... args)
-> decltype((std::declval<decltype(InferOwnerType(m))*>()->*m)(args...)) {
return (static_cast<decltype(InferOwnerType(m))*>(this)->*m)(args...);
}
public:
template <class... Args>
void update(Args... args) {
int arr[] = {(run(&SensorType::update, args...), 0)...};
(void)arr;
}
template <class... Args>
void updat2(Args... args) {
std::string s[] = {run(&SensorType::updat2, args...)...};
for (int i = 0; i < sizeof...(SensorType); i++)
std::cout << s[i] << std::endl;
}
};
int main() {
BaseSensor<EdgeSensor, TrendSensor> bs;
bs.update(4);
bs.updat2(0);
BaseSensor<EdgeSensor> bs2;
bs2.update(1);
bs2.updat2(0);
}
I asked How do I capture the results of a recursive function at compile-time?, but I think my approach was wrong.
I have a program like so:
#include <iostream>
#include <list>
std::list<unsigned int> recursive_case(std::list<unsigned int>& result, unsigned int& i) {
result.push_front(1 + (i % 10));
i /= 10;
return i != 0 ? recursive_case(result, i) : result;
}
std::list<unsigned int> initial_case(unsigned int i) {
std::list<unsigned int> result;
result.push_back(i % 10);
i /= 10;
return i != 0 ? recursive_case(result, i) : result;
}
int main() {
auto list = initial_case(123);
bool first = true;
for (auto i: list) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i;
}
std::cout << std::endl;
}
The output is 2, 3, 3.
I want to perform the above computation and get the same output but in compile-time (the loop iteration and output-printing would be at runtime i.e. everything starting from the for loop). Templates seem like a possibility (that's why I tagged this ask as such), but I am open to anything that gets the job done in compile-time.
You can use constexpr to calculate the list at compile time. I converted the recursion to iteration and used the indices trick to call calculate as often as necessary.
#include <iostream>
#include <array>
#include <iterator>
#include <utility>
constexpr std::size_t count_digits(std::size_t N, std::size_t Count = 0)
{
return (N > 0) ? count_digits(N/10, Count+1) : Count;
}
constexpr std::size_t ipow(std::size_t N, std::size_t Base)
{
return (N > 0) ? Base*ipow(N-1,Base) : 1;
}
constexpr std::size_t calculate(std::size_t n, std::size_t i)
{
std::size_t p = ipow(i,10);
std::size_t t = (n/p) % 10;
return i > 0 ? (t+1) : t;
}
template<std::size_t Num, std::size_t C, std::size_t... Is>
constexpr std::array<std::size_t, C> build_list(std::index_sequence<Is...>)
{
return {{ calculate(Num, C-Is-1)... }};
}
template <std::size_t Num, std::size_t C = count_digits(Num)>
constexpr auto build_list()
{
return build_list<Num, C>(std::make_index_sequence<C>{});
}
int main()
{
constexpr auto list = build_list<123>();
for(auto e : list)
{
std::cout << e << " ";
}
return 0;
}
output:
2 3 3
live example
Here's one solution.
#include <iostream>
// Print one digit.
template <unsigned int N, bool Initial> struct AtomicPrinter
{
static void print()
{
std::cout << N%10;
}
};
template <unsigned int N> struct AtomicPrinter<N, false>
{
static void print()
{
std::cout << 1 + N%10 << ", ";
}
};
// Recursive printer for a number
template <unsigned int N, bool Initial> struct Printer
{
static void print()
{
Printer<N/10, false>::print();
AtomicPrinter<N, Initial>::print();
}
};
// Specialization to end recursion.
template <bool TF> struct Printer<0, TF>
{
static void print()
{
}
};
void printList()
{
Printer<123, true>::print();
std::cout << std::endl;
}
int main() {
printList();
}
If there is a need to separate printing of the digits from constructing the list of digits, you can use:
#include <iostream>
#include <list>
template <unsigned int N, bool Initial> struct Digit
{
static void get(std::list<int>& l)
{
l.push_back(N%10);
}
};
template <unsigned int N> struct Digit<N, false>
{
static void get(std::list<int>& l)
{
l.push_back(1 + N%10);
}
};
template <unsigned int N, bool Initial> struct Digits
{
static void get(std::list<int>& l)
{
Digits<N/10, false>::get(l);
Digit<N, Initial>::get(l);
}
};
template <bool TF> struct Digits<0, TF>
{
static void get(std::list<int>& l)
{
}
};
void printList()
{
std::list<int> l;
Digits<123, true>::get(l);
bool first = true;
for (auto i: l) {
if (first) {
first = false;
} else {
std::cout << ", ";
}
std::cout << i;
}
std::cout << std::endl;
}
int main() {
printList();
}
You may use something like the following to split number at compile time:
#include <utility>
#include <iostream>
template <char... Cs>
std::integer_sequence<char, Cs...> operator "" _seq() { return {}; }
template <char...Cs>
void print(std::integer_sequence<char, Cs...>)
{
const char* sep = "";
for (const auto& c : {Cs...}) {
std::cout << sep << c;
sep = ", ";
}
}
int main() {
auto seq = 123_seq;
print(seq);
}
Demo
The goal of the code below is to implement a histogram where the bucket limits are template parameters:
#include <iostream>
#include <limits>
#include "histogram.h"
int main ( int argc, char* argv[] )
{
//histogram_tuple<5,10,15,std::numeric_limits<int>::max()> histogram;
histogram_tuple<5,10,15> histogram;
histogram.count ( 9 );
histogram.count ( 10 );
histogram.count ( 11 );
histogram.count ( 15 );
std::cout << sizeof ( histogram ) << std::endl;
std::cout << '<' << histogram.limit() << ' ' << histogram.count() << ", "
<< '<' << histogram.rest().limit() << ' ' << histogram.rest().count() << ", "
<< '<' << histogram.rest().rest().limit() << ' ' << histogram.rest().rest().count() << ", "
<< ' ' << histogram.rest().rest().rest().count()
<< std::endl;
std::cout << "====" << std::endl;
std::cout << '<' << bucket_limit<0>(histogram) << ':'
<< bucket_count<0>(histogram) << std::endl;
std::cout << '<' << bucket_limit<1>(histogram) << ':'
<< bucket_count<1>(histogram) << std::endl;
std::cout << '<' << bucket_limit<2>(histogram) << ':'
<< bucket_count<2>(histogram) << std::endl;
// std::cout << '<' << bucket_limit<3>(histogram) << ':'
// << bucket_count<3>(histogram) << std::endl;
}
The above works fine. With the repeated rest() calls, the count of the final bucket (values >= 15) is printed.
However, when the final line of main() is uncommented, g++ 4.7.1 generates a compiler error that bucket_limit_entry<0u> and bucket_count_entry<0u> are incomplete.
Any advice on how to get the convenience functions bucket_limit<3> to compile, since the repeated rest() calls work?
Not really sure what's going on. Changing the index type to int and making the termination case -1 instead of 0 didn't work.
Here's histogram.h:
#pragma once
template <int ... Limits>
class histogram_tuple;
template<>
class histogram_tuple<>
{
int cnt_;
public:
histogram_tuple<>() :
cnt_ ( 0 )
{
}
void count ( int value )
{
++cnt_;
}
int count() const
{
return cnt_;
}
};
template <int First, int ... Rest>
class histogram_tuple <First,Rest...> :
private histogram_tuple<Rest...>
{
static const int limit_ = First;
int cnt_;
public:
histogram_tuple <First,Rest...>() :
cnt_ ( 0 )
{ }
int limit() const { return limit_; }
void count ( int value )
{
if ( value < limit_ )
++cnt_;
else
rest().count ( value );
}
int count() const
{
return cnt_;
}
const histogram_tuple<Rest...>& rest() const
{
return *this;
}
histogram_tuple<Rest...>& rest()
{
return *this;
}
};
template <unsigned index, int ... Limits>
struct bucket_count_entry;
template <int First, int ... Limits>
struct bucket_count_entry<0,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return histogram.count();
}
};
template <unsigned index,int First, int ... Limits>
struct bucket_count_entry<index,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return bucket_count_entry<index-1,Limits...>::value(histogram.rest());
}
};
template <unsigned index,int ... Limits>
int bucket_count( histogram_tuple<Limits...> const& histogram )
{
return bucket_count_entry<index,Limits...>::value(histogram);
}
template <unsigned index, int ... Limits>
struct bucket_limit_entry;
template <int First, int ... Limits>
struct bucket_limit_entry<0,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return histogram.limit();
}
};
template <unsigned index,int First, int ... Limits>
struct bucket_limit_entry<index,First,Limits...>
{
static int value(histogram_tuple<First,Limits...> const& histogram)
{
return bucket_limit_entry<index-1,Limits...>::value(histogram.rest());
}
};
template <unsigned index,int ... Limits>
int bucket_limit( histogram_tuple<Limits...> const& histogram )
{
return bucket_limit_entry<index,Limits...>::value(histogram);
}
template <int First, int ... Limits>
bucket_limit_entry<0,First,Limits...>
won't match
bucket_limit_entry<0>
because First won't match nothing. (...Limits matches nothing, but First can only match one int).
So you need to add an additional template for the case where you've run out of limits:
template<>
struct bucket_limit_entry<0>
When you do that, you'll find that histogram<>::limit() is undefined, but you can easily fix that.
You'll need to do the same with bucket_count_entry, except that histogram<>::count() is defined.
The fact that you can't just define template<int...Limits> struct bucket_limit_entry<0, Limits...> {...} is a bit odd. The problem, as I understand it, is that both "Index is 0" and "Limits... has at least one element", are restrictions on the general template, and there is no arbitrary ordering between them. Consequently, template<int...Limits> struct X<0, Limits...> and template<unsigned index, int First, int...Rest> struct X<index, First, Rest...> are not ordered by the partial ordering for template specialization, and when both of them apply, you end up with an ambiguity.
But it seems to me that there is a simpler solution, since you can let the type of the histogram_tuple just be deduced:
template<unsigned Index> struct bucket_limit_entry {
template<typename Hist>
static int value(Hist const& histogram) {
return bucket_limit_entry<Index-1>::value(histogram.rest());
}
};
template<> struct bucket_limit_entry<0> {
template<typename Hist>
static int value(Hist const& histogram) {
return histogram.limit();
}
};
template<unsigned index, typename Hist>
int bucket_limit(Hist const& histogram ) {
return bucket_limit_entry<index>::value(histogram);
}
Is there an elegant way to specialize a template based on one of its template parameters?
Ie.
template<int N> struct Junk {
static int foo() {
// stuff
return Junk<N - 1>::foo();
}
};
// compile error: template argument '(size * 5)' involves template parameter(s)
template<int N> struct Junk<N*5> {
static int foo() {
// stuff
return N;
}
};
template<> struct Junk<0> {
static int foo() {
// stuff
return 0;
}
};
Ie. I am trying to specialize a template based on the parameter being divisible by 5. The only way I can seem to do it is like below:
template<int N> struct JunkDivisibleBy5 {
static int foo() {
// stuff
return N;
}
};
template<int N> struct Junk {
static int foo() {
// stuff
if ((N - 1) % 5 == 0 && N != 1)
return JunkDivisibleBy5<N - 1>::foo();
else
return Junk<N - 1>::foo();
}
};
template<> struct Junk<0> {
static int foo() {
// stuff
return 0;
}
};
But this is significantly less elegant, and also necessitates instantiation of all templates even if the template argument shouldn't require it.
How's this:
#include <iostream>
using namespace std;
template < typename T, T N, T D >
struct fraction {
typedef T value_type;
static const value_type num = N;
static const value_type denom = D;
static const bool is_div = (num % denom == 0);
};
template< typename T, T N, T D, bool P >
struct do_if {
static void op() { cout << N << " NOT divisible by " << D << endl; }
};
template< typename T, T N, T D >
struct do_if< T, N, D, true > {
static void op() { cout << N << " divisible by " << D << endl; }
};
template < int N >
void foo() {
typedef fraction< int, N, 5 > f;
do_if< typename f::value_type, f::num, f::denom, f::is_div >::op();
}
int main() {
foo< -5 >();
foo< -1 >();
foo< 0 >();
foo< 1 >();
foo< 5 >();
foo< 10000005 >();
return 0;
}
Using D programming language templates, one could write it as:
struct Junk(int N)
{
static int foo()
{
static if (N == 0)
return 0;
else static if ((N % 5) == 0)
return N;
else
return Junk!(N - 1).foo();
}
}
static if's are executed at compile time.
All calculations could be made in compile-time:
#include <iostream>
template<int N> struct Junk {
enum { IsDivisibleBy5 = (N % 5 == 0) };
template<bool D> struct JunkInternal {
enum { Result = Junk<N-1>::Result };
};
template<> struct JunkInternal<true> {
enum { Result = N };
};
enum { Result = JunkInternal<IsDivisibleBy5>::Result };
};
int main(int, char**)
{
std::cout << Junk< 0 >::Result << std::endl;
std::cout << Junk< 7 >::Result << std::endl;
std::cout << Junk< 10 >::Result << std::endl;
return 0;
}
Code
template<int A, bool = !(A % 5)>
struct select : select<A-1> { };
template<int A>
struct select<A, true> { static int const value = A; };
template<>
struct select<0, true> { static int const value = 0; };
int main() {
std::cout << select<1>::value; // 0
std::cout << select<7>::value; // 5
std::cout << select<10>::value; // 10
}
Keep the divisor variable
template<int A, int D, bool = !(A % D)>
struct select : select<A-1, D> { };
template<int A, int D>
struct select<A, D, true> { static int const value = A; };
template<int D>
struct select<0, D, true> { static int const value = 0; };
int main() {
std::cout << select<1, 3>::value; // 0
std::cout << select<7, 3>::value; // 6
std::cout << select<10, 3>::value; // 9
}
Inheritance works quite well:
template<int N> struct Junk : private JunkBase < N % 5 > { };
template<int N> struct JunkBase {
static int foo() {
// stuff
return Junk<N - 1>::foo();
}
};
template< > struct JunkBase<0> {
static int foo() {
return 0;
}
};
You might need to pass N to JunkBase::foo, if you need N/5 too.
I would hardly call it elegant, but here's my version of your code using only templates for computation (along with a test thing) --
#include <iostream>
template < int N > struct JunkDivBy5 {
static int foo() {
return N;
}
};
template < int N > struct Junk {
template < int N1 > struct _JunkCond {
enum { val = ( N1 != 1 && ( N1 - 1 ) % 5 == 0 ) ? 1 : 0 };
};
template < int M, int N1 > struct _JunkBranch { /* Error */ };
template < int N1 > struct _JunkBranch< 1, N1 > {
typedef JunkDivBy5< N1 - 1 > Type;
};
template < int N1 > struct _JunkBranch< 0, N1 > {
typedef Junk< N1 - 1 > Type;
};
static int foo() {
return _JunkBranch< _JunkCond< N >::val, N >::Type::foo();
}
};
template <> struct Junk< 0 > {
static int foo() {
return 0;
}
};
int main( int argc, char *argv[] ) {
std::cout << Junk< 0 >::foo() << std::endl;
std::cout << Junk< 5 >::foo() << std::endl;
std::cout << Junk< 7 >::foo() << std::endl;
std::cout << Junk< 25 >::foo() << std::endl;
}