Search code examples
c++templatestypedefc++14using

Partial typedef (`using`) of a templated function


Trying to implement a dot product function using templates, I have written the following templated function.

template <typename T, typename R = float,
  typename = 
    std::enable_if_t<std::is_arithmetic<decltype(std::declval<T>().x)>{}>,
  typename = 
    std::enable_if_t<std::is_arithmetic<decltype(std::declval<T>().y)>{}>>
constexpr R dot(const T a_vector, const T b_vector)
{
    return a_vector.x * b_vector.x + a_vector.y * b_vector.y;
}

I want my users to also easily use the dot function returning a double instead of the default float. That's why I am using a using to "typedef" the dot().

template<typename T, typename R, typename ... >
using dotd = dot<T, double>;

This code yields

  • in g++ error: ‘dot<T, float>’ does not name a type
  • in clang++ error: expected a type and error: expected ';' after alias declaration

Do I have an option to use an alternative for functions?


Solution

  • You could just flip the ordering of the template arguments. If you place R first, it's easy for the user to simply provide a different type for it if that's what they want:

    template <
      typename R = float,
      typename T,
      typename = 
        std::enable_if_t<std::is_arithmetic<decltype(std::declval<T>().x)>{}>,
      typename = 
        std::enable_if_t<std::is_arithmetic<decltype(std::declval<T>().y)>{}>>
    constexpr R dot(const T a_vector, const T b_vector)
    {
        return a_vector.x * b_vector.x + a_vector.y * b_vector.y;
    }
    

    And then dot(a, b) gives you a float vs dot<double>(a, b) gives you a double. I find dot<double> a lot clearer than having to look up what dotd means.

    Though if you're using C++14, better to simply drop the R template argument completely and return auto.