От: | Alexey F | ||
Дата: | 27.10.09 20:36 | ||
Оценка: | 70 (3) |
foo ( value< char, value_int<char, 'c'> > x, value< double, value_func<double, Functor> > y ... )
...
#include <cmath>
enum placeholder { _ }; // Нехорошо, наверное (:xz:), нижним подчёркиванием, но оставим так для чистоты в коде примера.
// Целые значения:
// (оставил почти без изменений)
template<class T, T V = T()>
struct i_param // integer parameter
{
i_param () : value(V) {}
i_param (placeholder) : value(V) {}
template<class U> i_param (U u) : value(u) {}
T get() const { return value; }
operator T() const { return value; }
T value; // оставим открытым на случай, если надо будет адрес взять, например.
};
// Дробные значения:
// Вспомогательный код:
namespace aux {
// long/long long по вкусу
typedef long long integral_part;
typedef unsigned long long rational_part;
template<rational_part number>
struct digits_in_number {
enum { result = 1 + digits_in_number<number / 10>::result };
};
template<>
struct digits_in_number<0> {
enum { result = 0 };
};
}
template<class T, aux::integral_part Integral, aux::rational_part Rational>
struct f_param { // float parameter
f_param () : value ( makeValue () ) {}
f_param ( placeholder ) : value ( makeValue () ) {}
template<class U>
f_param ( U const& other )
: value ( other ) {}
T get () const {
return value;
}
operator T () const {
return value;
}
T value;
private:
inline T makeValue () const {
return
( std::abs ( static_cast<T> ( Integral ) ) + ( Rational * std::pow ( 10, -aux::digits_in_number<Rational>::result ) ) )
* ( Integral >= 0 ? 1 : -1 )
;
}
};
// Ну и, наконец, произвольные значения (в том числе и времени выполнения), которые получаются через функтор
// (только вот параметры ему не передашь):
template<class T, class Functor>
struct func_param { // functor parameter
func_param () : value ( Functor ()() ) {}
func_param ( placeholder ) : value ( Functor ()() ) {}
template<class U>
func_param ( U const& other )
: value ( other ) {}
T const& get () const {
return value;
}
operator T const& () const {
return value;
}
T value;
};
...
struct SimpleGetter {
std::string operator ()() const {
return "test";
}
};
void foo (
i_param<char, 'c'> x,
i_param<int, 7> y,
i_param<unsigned, 9> z,
f_param<double, 3,14> a, // запятая, а не точка!
func_param<std::string, SimpleGetter> b // std::string const& в такой форме уже не сделаешь :)
)
{
cout << x.get() << " " << y.get() << " " << z.get() << ' ' << a.get () << ' ' << b.get () << endl;
}
int main()
{
foo('a', _, _, _, _ );
foo( _, 2, _, _, "test 2" );
foo( _, _, -3, 3.14159, _ );
}
a 7 9 3.14 test
c 2 9 3.14 test 2
c 7 4294967293 3.14159 test
...
int main () {
printf ( "%f", f_param<double, 3,14159> ().get () );
}
00401356 |. C74424 04 6E861BF0 MOV DWORD PTR SS:[ESP+4],F01B866E ; |
0040135E |. C74424 08 F9210940 MOV DWORD PTR SS:[ESP+8],400921F9 ; |
00401366 |. C70424 24304700 MOV DWORD PTR SS:[ESP],default_.00473024 ; |ASCII "%f"
0040136D |. E8 2EFD0100 CALL <JMP.&msvcrt.printf> ; \printf
printf ( "%f", 3.14159 );