Traté de implementar la especialización de funciones de plantilla. Puede ejecutar mi pequeño código en este violín. También puedes verlo a continuación

#include <iostream>
#include <vector>
#include <list>


template <typename T>
struct is_vector {
    static const bool value = false;
};

template <typename T>
struct is_vector<std::vector<T>> {
    static const bool value = true;
    using type = std::vector<T>;
};

template <typename T>
struct is_list {
    static const bool value = false;
};

template <typename T>
struct is_list<std::list<T>> {
    static const bool value = true;
    using type = std::list<T>;
};


template<typename T, class = typename std::enable_if<is_list<T>::value>::type>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

/*
template<typename T, class = typename std::enable_if<is_vector<T>::value>::type>
void foo(T t) {
    std::cout << "is vector" << std::endl;
}
*/
//The above code will cause an error, if we uncomment it

int main()
{

    foo(std::list<int>{});    

    return 0;
}

En este código, tengo varias líneas comentadas:

template<typename T, class = typename std::enable_if<is_vector<T>::value>::type>
void foo(T t) {
    std::cout << "is vector" << std::endl;
}

Si lo descomento, aparece el error de "redefinición". No estoy seguro de cómo solucionarlo.

c++
0
Jacobian 20 ene. 2018 a las 21:57

3 respuestas

La mejor respuesta

Puedes hacer esto en su lugar.

template<typename T>
typename std::enable_if<is_list<T>::value>::type foo(T t) {
    std::cout << "is list" << std::endl;
}


template<typename T>
typename std::enable_if<is_vector<T>::value>::type foo(T t) {
    std::cout << "is vector" << std::endl;
}
1
super 20 ene. 2018 a las 19:10

Si lo descomento, aparece el error de "redefinición". No estoy seguro de cómo solucionarlo.

La razón es bastante simple: los valores predeterminados para los argumentos de tipo de plantilla no son parte de una firma de función. Significa que tiene la misma plantilla definida dos veces.

Puede mover la parte SFINAE al tipo de retorno de función, como lo sugieren otras respuestas, o cambiar el código a:

template<typename T, std::enable_if_t<is_list<T>::value, int> = 0>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

template<typename T, std::enable_if_t<is_vector<T>::value, int> = 1>
void foo(T t) {
    std::cout << "is vector" << std::endl;
}
3
Edgar Rokjān 20 ene. 2018 a las 19:17

No estoy seguro de si esto es lo que busca, pero podría verificar si la lista o el vector coinciden:

template<typename T, class = typename std::enable_if<is_list<T>::value || is_vector<T>::value>::type>
void foo(T t) {
    std::cout << "is list" << std::endl;
}

Violín actualizado: https://godbolt.org/g/oD3o9q

Actualización (para C ++ 14):

template<typename T, class = std::enable_if_t<is_list<T>::value || is_vector<T>::value>>
void foo(T t) {
    std::cout << "is list" << std::endl;
}
1
HolyBlackCat 20 ene. 2018 a las 19:30