Tengo un método C ++ findID que usa plantillas, y quiero poder ejecutar una condición en este método según el tipo de entrada. El parámetro de plantilla U será de tipo int o de tipo cadena. Quiero ejecutar una condición diferente según el tipo de identificación.

El código que tengo es el siguiente:

template <typename S>
template <typename U>
S * findID(U ID){
    for (typename vector<S*>::collectionsIter element = collection.begin() ; element != collection.end(); ++element)
        if((*element)->getID() == ID) return *element;
    return NULL;
}

Quiero que mi código haga lo siguiente:

template <typename S>
    template <typename U>
    S * findID(U ID){

      ***if ID is an int:
        for (typename vector<S*>::collectionsIter element = collection.begin() ; element != collection.end(); ++element)
            if((*element)->getID() == ID) return *element;


      ***if ID is a string:

         for (typename vector<S*>::collectionsIter element = collection.begin() ; element != collection.end(); ++element)
            if((*element)->getStringID() == ID) return *element;

       ***else 

        return NULL;


    }

La razón por la que quiero hacer esto es porque quiero poder comparar las variables de cadena de ID con el método de cadena de getStringID (), y las variables int de ID con el método int de getID (). Además, no quiero dividirlos en métodos separados, por lo que estoy tratando de usar plantillas y estas condiciones para refactorizarlo en 1 método.

3
MastRofDsastR 15 nov. 2017 a las 07:21

2 respuestas

La mejor respuesta

Solo use 2 sobrecargas:

template <typename S>
S* findID(int ID){
    for (auto* element : collection)
        if (element->getID() == ID) return element;
    return nullptr;
}

template <typename S>
S* findID(const std::string& ID){
    for (auto* element : collection)
        if (element->getStringID() == ID) return element;
    return nullptr;
}
3
Jarod42 15 nov. 2017 a las 09:01

Aquí hay una forma de hacerlo usando C ++ 17 if constexpr:

struct Foo {
    int id;
    std::string stringId;

    int getId() const { return id; }
    const std::string& getStringId() const { return stringId; }
};

template <typename Cont, typename T>
auto findId(const Cont& c, const T& id) {
    const auto pred = [&id](const auto& x) {
        if constexpr (std::is_convertible_v<T, std::string>)
            return x.getStringId() == id;
        else if constexpr (std::is_convertible_v<T, int>)
            return x.getId() == id;
        else
            static_assert(false, "Unsupported id type.");
        return false;
    };
    const auto findIt = std::find_if(begin(c), end(c), pred);
    return findIt == end(c) ? nullptr : &(*findIt);
}

int main() {
    using namespace std;
    vector<Foo> foos{{1, "1"}, {2, "2"}, {3, "3"}};
    auto foo2Int = findId(foos, 2);
    auto foo2String = findId(foos, "2"s);
    cout << foo2Int->id << ", " << foo2String->stringId << '\n';
}
1
mattnewport 15 nov. 2017 a las 06:30