Как определить тип возвращаемого значения функции? - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь построить вектор объектов, имеющих два свойства, ключ всегда является строкой, а значение всегда имеет тип T

Когда я выполняю итерацию по вектору, мне нужновозможность определить тип свойства value, чтобы я мог переключаться в операторе case для его обработки.

Как определить тип возвращаемого значения value, получить функцию векторного объекта?

Мой класс здесь:

template <class T>
class IEFIAttribute
{
    String key;
    T value;
    public: 
            IEFIAttribute(String key, T value)
            {
                this->key = key;
                this->value = value;
            }
            String getKey();
            T getValue();
};

template <class T>
String IEFIAttribute<T>::getKey()
{
    return this->key;
}

template <class T>
T IEFIAttribute<T>::getValue()
{
    return this->value;
}

И в моем main.cpp следующие работы:

...
                IEFIAttribute <String> att("testkey","testvalue");

                Serial.println("XXX Key: "+att.getKey());
                Serial.println("XXX Value: "+att.getValue());
...

Результат выполнения:

XXX Key: testkey
XXX Value: testvalue

Что я хочу сделать, это включить тип att.getValue(), чтобы, если это строка, я выполнял одно действие, если это объект xyz, обрабатывал его в соответствии со своими правилами для объектов xyz.

Буду очень признателен за любую помощь!

С уважением!

Ответы [ 2 ]

3 голосов
/ 03 октября 2019
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>

using String = std::string;

template<class T>
class IEFIAttribute {
public:
    using value_type = T;   // add this to be able to query it later

    IEFIAttribute(const String& Key, const T& Value) : 
        key(Key),           // prefer using the member initializer list
        value(Value) 
    {}

    // instead of copies, return const references
    String const& getKey() const {
        return key;
    };
    T const& getValue() const {
        return value;
    }

private:
    String key;
    T value;
};

У вас есть много возможностей сделать специальную обработку для определенных типов.

Шаблон, использующий constexpr, если :

template<typename T>
T special_1(const std::vector<IEFIAttribute<T>>& v, size_t idx) {
    if constexpr(std::is_same_v<T, String>) {
        std::cout << "special_1() String handler\n";
    } else if constexpr(std::is_same_v<T, int>) {
        std::cout << "special_1() int handler\n";
    } else {
        std::cout << "special_1() generic handler\n";
    }
    return v[idx].getValue();
}

Шаблон со специализациями:

template<typename T>
T special_2(const std::vector<IEFIAttribute<T>>& v, size_t idx) {
    std::cout << "special_2() generic handler\n";
    return v[idx].getValue();
}

template<>
String special_2(const std::vector<IEFIAttribute<String>>& v, size_t idx) {
    std::cout << "special_2() String handler\n";
    return v[idx].getValue();
}

template<>
int special_2(const std::vector<IEFIAttribute<int>>& v, size_t idx) {
    std::cout << "special_2() int handler\n";
    return v[idx].getValue();
}

Или используя добавленный value_type для выполнения запросов:

int main() {
    std::vector<IEFIAttribute<String>> v1{{"testkey", "testvalue"}};
    std::vector<IEFIAttribute<int>> v2{{"testkey", 10}};

    // decltype(v1)::value_type is the vectors value_type
    // and the second value_type is the one added to your class

    if(std::is_same_v<decltype(v1)::value_type::value_type, String>) {
        std::cout << "is String\n";
    } else {
        std::cout << "is not String\n";
    }

    if(std::is_same_v<decltype(v2)::value_type::value_type, int>) {
        std::cout << "is int\n";
    } else {
        std::cout << "is not int\n";
    }

    std::cout << special_1(v1, 0) << "\n";
    std::cout << special_1(v2, 0) << "\n";
    std::cout << special_2(v1, 0) << "\n";
    std::cout << special_2(v2, 0) << "\n";
}
1 голос
/ 03 октября 2019

Один из способов выполнить то, что вам нужно, - это использовать typedef внутри вашего класса, а затем функции <type_traits> для ваших условных операторов.

Например:

template <class T>
class IEFIAttribute
{
  public:
    typedef T value_type;

  // everything as before...

};

тогда

if (std::is_same<att::value_type, String>)
  // .. do something
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...