2
template <typename IN,typename OUT,bool isVector>
OUT foo(IN x){
    if (isVector){
        return x[0];     
    } else {
        return x;
    }
}

After asking this question I wrongly assumed, that the above code could compile for e.g.

foo<double,double,false>;

as well as

foo<std::vector<double>,double,true>;

However, even if one of the if-branches never gets executed, it is checked for correctness and thus the above does not compile. How can I fix it?

The code above is a simplified, but I dont know how to fix it, as function templates cannot have partial specialization...

Community
  • 1
  • 1
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185

1 Answers1

4

You can "extract" the template parameters you want to specialize on, make them the template parameters of some structure, and write the function with the remaining template parameters as static member function:

template<bool IsVector = true>
struct Bar {
    template<typename In>
    static auto foo(In input) {
        return input[0];
    }
};
template<>
struct Bar<false> {
    template<typename In>
    static auto foo(In input) {
        return input;
    }
};

Live example.

Obviously this results in a change at the call site, which you can "catch" using a free function that is calling the appropriate function:

template<typename In, bool IsVector>
auto real_foo(In input) {
  return Bar<IsVector>::foo(input);
}

The structures (Bar) are then normally put inside an "helper" namespace.


Another possibility is to use tags and overload resolution:

template<typename In>
auto foo(In input, std::true_type) {
    return input[0];
}
template<typename In>
auto foo(In input, std::false_type) {
    return input;
}
template<bool IsVector, typename In>
auto foo(In input) {
    using tag = typename conditional<IsVector, true_type, false_type>::type;
    return foo(input, tag{});
}

Live example.

This uses std::conditional with std::true_type and std::false_type as different types to allow overload resolution to find the appropriate foo function.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • looks fine, I will try it – 463035818_is_not_an_ai Nov 01 '15 at 19:01
  • I prefer the first solution, the second looks like c++11 which i cannot use unfortunately. However, I cannot get it running when calling the function from within a templated class `A` and the template parameters i am passing (`In` in your code) are template parameters of `A`. Any idea why this could be? I will try to make into an MCVE... – 463035818_is_not_an_ai Nov 01 '15 at 19:59
  • ... I know, that I could partially specialize `A`, but it is a rather big class and I would like to avoid introducing a base class just for that purpose. – 463035818_is_not_an_ai Nov 01 '15 at 20:17
  • Your example isn't compiling because the compiler cannot deduce that `foo` is a template. You need to tell that explicitly: http://ideone.com/TJp3KT – Daniel Jour Nov 01 '15 at 22:44
  • Note that the second solution indeed uses C++11 features, but you could write these yourself very easily. – Daniel Jour Nov 01 '15 at 22:46