Шаблоны C ++ 11 и обратный вызов возвращают типы с void специализацией / перегрузкой - PullRequest
0 голосов
/ 06 марта 2020

Это немного надуманный пример, но наименьшее количество кода для воспроизведения моего вопроса.

Здесь я передаю обратный вызов функции, а результат преобразуется в строку и помещается в вектор. Это прекрасно работает для любого типа с to_string реализацией. (Я использую указатели на функции вместо std :: function, потому что некоторые функции поступают из сторонних C библиотек)

#include <vector>
#include <string>

template<typename R>
void Example(std::vector<std::string> &vec, R (*func)()) {
    auto r = func();
    vec.push_back(std::to_string(r));
}

int main(int argc, char **argv ) {
    std::vector<std::string> vec;

    Example(vec, static_cast<int(*)()>([]() -> int{
        return 0;
    }));

    Example(vec, static_cast<double(*)()>([]() -> double{
        return 0.0;
    }));
} 

Однако один особый случай - void. В этом случае я не хочу, чтобы что-либо было добавлено к вектору.

// This obviously does not compile.
Example(vec, static_cast<void(*)()>([](){
    auto a = 0;
}));

Я знаю, что могу перегрузить Example, то есть

void Example(std::vector<std::string> &vec, void (*func)()) {
    func();
}

Но в моем приложении реального мира Example НАМНОГО сложнее, и перегрузка приводит к большому количеству кода, вставленного в копию. Я попытался использовать type_traits Но не смог заставить это работать.

Есть ли другой подход, который мне не хватает?

1 Ответ

2 голосов
/ 06 марта 2020

if constexpr позволяет условно компилировать код, учитывая, что условие зависит от параметра шаблона. Для этого требуется C ++ 17 для if constexpr и #include<type_traits> для черты типа std::is_same_v.

template<typename R>
void Example(std::vector<std::string> &vec, R (*func)()) {
    if constexpr(std::is_same_v<R, void>) {
        func();
    } else {
        auto r = func();
        vec.push_back(std::to_string(r));
    }
}
...