I have a maths function that I want to be able to accept either a double, or a vector of doubles, and behave slightly differently.
I am attempting to use SFINAE and type traits to select the correct function.
Here is a minimal example:
#include <iostream>
#include <vector>
#include <type_traits>
template <typename T>
constexpr bool IsVector()
{
if constexpr (std::is_class<T>::value && std::is_arithmetic<typename T::value_type>::value) {
return true;
}
return false;
}
// Function 1 (double):
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type g(T const & t)
{
std::cout << "this is for a double" << t << std::endl;
}
// Function 2 (vec), version 1:
template <typename T>
typename std::enable_if<IsVector<T>()>::type g(T const & t)
{
std::cout << "this is for a vector" << t[0] << std::endl;
}
int main()
{
std::vector<double> v {1, 2};
double d {0.1};
g<>(v);
g<>(d); // error here
}
I get a compile time error:
../main.cpp:8:47: error: ‘double’ is not a class, struct, or union type
if constexpr (std::is_class<T>::value && std::is_arithmetic<typename T::value_type>::value) {
~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
However, when I replace function 2 with:
// Function 2 (vec), version 2:
template <typename T>
typename std::enable_if<std::is_class<T>::value && std::is_arithmetic<typename T::value_type>::value>::type
g(T const & t)
{
std::cout << "this is for a vector" << t[0] << std::endl;
}
It works.
My problem is I don't understand why the first version does not work.. And I prefer the readability of the first version.
Aucun commentaire:
Enregistrer un commentaire