1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/preprocessor/repetition.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/numeric.hpp>
#include <boost/lexical_cast.hpp>
template <size_t size_seq>
struct sum
{
unsigned int pos_seq;
unsigned int pos_range;
unsigned int occurrences;
sum(unsigned int posSeq) : pos_seq(posSeq), pos_range(1), occurrences(0) {}
template<typename T>
unsigned int operator()(unsigned int &sum, const T& t)
{
unsigned int c = 0;
try{
c = boost::lexical_cast<unsigned int>(t);
if(pos_range++ % (pos_seq + occurrences*size_seq) == 0)
++occurrences;
else
c = 0;
}catch(boost::bad_lexical_cast){ } // Characters ignored.
return sum + c;
}
};
template<class Range, size_t N>
struct Func
{
size_t i_;
const Range& r_;
unsigned int& sum_;
Func(const Range& r, unsigned int &sum) : i_(0), r_(r), sum_(sum) {}
template<class T, T I>
void operator()(const boost::mpl::integral_c<T,I>&)
{
++i_;
sum_ += I * boost::accumulate(r_ , unsigned int(), sum<N>(i_) );
}
};
template<class Seq, class Range>
typename boost::range_value<Range>::type foo_impl(const Range& r)
{
unsigned int sum = 0;
boost::mpl::for_each<Seq>(Func<Range, boost::mpl::size<Seq>::value>(r, sum));
return boost::lexical_cast<boost::range_value<Range>::type>((10 - sum % 10) % 10) ;
}
#define FOO_impl(z,n,unused) \
template<BOOST_PP_ENUM_PARAMS(n, int I) BOOST_PP_COMMA_IF(n) class Range> \
typename boost::range_value<Range>::type foo(const Range& r) \
{ return foo_impl<boost::mpl::vector_c<int BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, I)> >(r); }
BOOST_PP_REPEAT(10,FOO_impl,~)
#undef FOO_impl
int main()
{
//unsigned int number[] = {1,2,3} ;
std::string number = "1-2-3";
std::cout << "Check digit : " << foo<1,2,3>(number) << std::endl;
return 0;
} |
Partager