Tag dispatching is the way to go.
template<class T>
void func_impl( std::true_type T_is_Foo ) {
T t(1);
}
template<class T>
void func_impl( std::false_type T_is_Foo ) {
T t("aaa");
}
template<typename T>
void func(){
return func_impl( std::is_same<T,Foo>{} );
}
You can mess around with template function specialization or SFINAE; both are fragile. Template function specialization behaves unlike similar features elsewhere in C++, and SFINAE is impenetrable.
Another option in C++14 is to write a static if using lambdas. This is impenetrable, but at least isolated from your actual code:
struct do_nothing{ template<class...Ts> void operator()(Ts&&...){} };
template<class F_true, class F_false=do_nothing>
auto static_if( std::true_type, F_true&& f_true, F_false&& f_false = do_nothing{} ) {
return std::forward<F_true>(f_true);
}
template<class F_true, class F_false=do_nothing>
auto static_if( std::false_type, F_true&& f_true, F_false&& f_false = do_nothing{} ) {
return std::forward<F_false>(f_false);
}
template<typename T>
void func(){
static_if( std::is_same<T,Foo>{}, [&](auto&&){
T t(1);
}, [&](auto&&){
T t("abc");
})(1);
}
which at least looks like an if
statement. static_if
returns the second or third argument depending on the static truth value of its first argument.
In this case, we pass in lambdas. We then invoke the return value.
Only the lambda that matches the truth value of the first argument is invoked.