2016-10-24 49 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{}); 
}