реализация карты функций c ++ - PullRequest
5 голосов
/ 23 ноября 2011

Я играл с переменными шаблонами в новом стандарте c ++ и придумал функцию карты (исключая заголовки + использование дека):

template<typename T>
T square(T i)
{
        return i * i;
}

template <typename T, typename... Ts>
const tuple<Ts...> map(const T f, const Ts...args)
{
        return make_tuple(f(args)...);
}

int main(int c, char *argv[])
{
        tuple<int, int> t;
        int (*fp) (int) = square;

        t = map(fp, 6, 8);

        cout <<get<0>(t) <<endl;
        cout <<get<1>(t) <<endl;

        return 0;
}

Который работает. Пока все аргументы имеют одинаковый тип для карты. Если я изменю основную, чтобы использовать немного более общую форму:

 tuple<int, float> t;

 t = map(square, 6, 8.0f);

gcc 4.4 сообщает:

In function ‘int main(int, char**)’:
error: no matching function for call to ‘map(<unresolved overloaded function type>, int, float)’

Есть идеи, как заставить это работать?

1 Ответ

5 голосов
/ 23 ноября 2011

Во-первых, вы не можете передавать неразрешенный шаблон функции в качестве указателя (или параметра шаблона), вы можете только передавать его экземпляры.Это означает, что первый аргумент вашего шаблона передается как int (*)(int) в этом примере, и он не может вызвать экземпляр float (*)(float).Я не уверен, что это лучший способ исправить это, но в любом случае это технически не то, о чем вы спрашивали.

У меня нет компилятора для тестирования, но я думаю, что если вы используете std::functionчтобы вывести типы, которые хочет передать передаваемая вами функция, вы можете преобразовать параметры в функцию.Вот так:

template<typename T, typename Ts...>
tuple<Ts...> map(std::function<T (T)> const &f, Ts... args) {
    return make_tuple(static_cast<Ts>(f(static_cast<T>(args)))...);
}

Видите, я думаю, вам нужно привести как параметр (как T), так и тип возвращаемого значения (как Ts) для функции, так как это кажется неявным преобразованиемправила не работают внутри этого шаблона.

Если мой синтаксис не работает (вероятно, нет, ... сложно, если у вас нет компилятора для них), это может бытьвозможно, что вы могли бы переписать это как гораздо более многословную функцию, которая распаковывает каждый Ts перед вызовом функции, а затем создает кортеж по ходу работы.Я не уверен, действительно ли это необходимо, но я чувствую, что поддержка компилятора для всех распаковок ... сейчас немного затруднена, поэтому даже если вы придумали что-то, что должно работать, я бы не сталУдивлен, если ваш компилятор не смог справиться с этим.

...