Przy pomocy tego kodu będziesz mieć problemy. Jeśli chcesz rozróżnić różne cechy typu, należy to zrobić w czasie kompilacji, a nie w czasie wykonywania. W zależności od wykonywanej operacji jedna z dwóch gałęzi twojego if
może nie zostać skompilowana. Więc lepiej jest przekazać do wyspecjalizowanej funkcji:
void operation_impl(boost::true_type /*other params*/) {
// Treat it is primitive
}
void operation_impl(boost::false_type /*other params*/) {
// Treat it otherwise
}
template<class T>
void operation(/* params*/) {
operation_impl(boost::is_fundamental<T>::type() /*other params*/);
}
Dzięki tej technice realizacji tylko używane oddział musi skompilować (to znaczy być poprawne).
Edit:
Oto niektóre dodatkowe informacje. Rozwiązanie tego problemu wiąże się z instancją szablonów. Przełączam się z is_fundamental
na is_array
, aby pokazać, jak operacje mogą się nie udać.
Zacznijmy od pierwszego przykładu:
template <class T>
void fun(T t) {
if(boost::is_array<T>::value)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
}
void f(int i) {
fun(i);
}
To będzie skompilować i uruchomić i kompilator będzie widać, że tylko jeden oddział if zostaną wykorzystane i usunie drugi jako niewykorzystany kod.
W moim drugim przykładzie zrobię someithing w przypadku używam operację tablicy:
template<class T>
void fun(T& t) {
if(boost::is_array<T>::value)
{
std::cout << t[0];
}
else
{
std::cout << t;
}
}
void f(int i) {
fun(i);
}
Teraz nie będzie skompilować. Powód jest z int jako szablon argumentem t[0]
jest źle sformułowany. Nie możesz użyć tej instrukcji środowiska wykonawczego do rozróżnienia właściwości typów w czasie kompilacji, które są potrzebne w kodzie (w tym przykładzie właściwość tablicy i użycie t[0]
).
W trzecim przykładzie będziemy disitinguish na czasie kompilacji za pomocą funkcji przeciążenia:
template<class T>
void fun_impl(boost::true_type, T& t) {
std::cout << t[0];
}
template<class T>
void fun_impl(boost::false_type, T& t) {
std::cout << t;
}
template<class T>
void fun(T& t) {
fun_impl(typename boost::is_array<T>::type(),t);
}
void f(int i) {
fun(i);
}
Tutaj is_array<T>::type
jest albo true_type
lub false_type
. Wynik ten jest używany jako selektor do wyboru właściwego przeciążenia fun_impl
w czasie kompilacji i tylko wybrane przeciążenie jest instanziowane i kompilowane.
Zwykle takie techniki są wykorzystywane do wyboru w dogodnym dla siebie terminie najlepszego wykonania, które może być kompilowane tylko wtedy, gdy typy mają określone właściwości.
2-ty edit:
ten ulegnie oczywiście zmianie jeśli static if
jest częścią języka.
Dzięki. +1 dla "włączenia". – Subway