2016-10-24 43 views
4

我有一個模板功能,並在一個點上,我想這取決於模板參數有不同的代碼:分支函數中的模板參數?

template <typename T> 
void function(const T &param) { 
    // generic code here... 

    // pseudo-code: 
    if constexpr isinstance(param, Banana) { 
     param.peel(); 
    } else if constexpr isinstance(param, Apple) { 
     // do nothing, Apple has no method `peel` 
    } 
} 

我不想專門整體功能,因爲大部分代碼共享。我想插入的語句是一個臨時調試措施。我知道正確的做法是創建一個重載函數doPeel而改爲調用:

void doPeel(const Banana &param) { param.peel(); } 
void doPeel(const Apple &param) {} 

但我很好奇,有沒有辦法告訴在編譯時,在一個函數,什麼(模板特)鍵入一個給定的變量是...爲了使用只能編譯一種類型的語句?

我不知道constexpr之類的東西是否可能 - 或者編譯器是否在丟棄的分支中執行類型?我也嘗試用lambda表達式來定義lambda表達式 - 爲兩種情況定義lambda表達式,並且只調用一個lambda表達式,但是我找不到辦法做到這一點。有任何想法嗎?

回答

2

有一個在C++ 17 if constexpr

template<typename T> 
void foo(T const& t) 
{ 
    if constexpr(is_same<decay_t<T>, int>::value) { 
     cout << __PRETTY_FUNCTION__ << " " << t * 2 << endl; 
    } else { 
     cout << __PRETTY_FUNCTION__ << endl; 
    } 
} 

live demo


在C++ 14,你可以破解這樣的事情:

template<typename T> 
void foo(T const& t) 
{ 
    conditional_eval<is_same<decay_t<T>, int>>([=](auto){ 
     cout << __PRETTY_FUNCTION__ << " " << t * 2 << endl; 
    },[](auto){ 
     cout << __PRETTY_FUNCTION__ << endl; 
    }); 
} 

隨着conditional_eval定義如:

template<typename IfTrue, typename IfFalse> 
void conditional_eval_impl(std::true_type, IfTrue&& t, IfFalse&&) { 
    t(0); 
} 

template<typename IfTrue, typename IfFalse> 
void conditional_eval_impl(std::false_type, IfTrue&&, IfFalse&& f) { 
    f(0); 
} 

template<typename Tag, typename IfTrue, typename IfFalse> 
void conditional_eval(IfTrue&& t, IfFalse&& f) { 
    conditional_eval_impl(Tag{}, std::forward<IfTrue>(t), std::forward<IfFalse>(f)); 
} 

live demo

+0

嗯我想它會花費比C + + 11最小的變化更多,因爲你依靠通用lambdas推遲解析的lambda身體,不是? –

+0

@LightnessRacesinOrbit這是真的,我沒有想到通過 – krzaq

3

在C++ 14,你可以使用通用的λ例如仿效if constexpr通過:

#include <type_traits> 
#include <iostream> 

template <bool B> 
struct constexpr_if { 
    template <class Lambda, class T> 
    static void then(Lambda l, T&& value) { } 
}; 

template <> 
struct constexpr_if<true> { 
    template <class Lambda, class T> 
    static void then(Lambda l, T&& value) { 
     l(std::forward<T>(value)); 
    } 
}; 


struct Banana { 
    void peel() const { 
    std::cout << "Banana::peel" << std::endl; 
    } 
}; 

struct Apple { 
}; 

template <typename T> 
void function(const T &param) { 
    constexpr_if<std::is_same<T, Banana>::value>::then([&](auto &p){ 
     p.peel(); 
    }, param); 
} 

int main() { 
    function(Banana{}); 
    function(Apple{}); 
}