Visual Studio 2010 и std :: function - PullRequest
       30

Visual Studio 2010 и std :: function

11 голосов
/ 11 марта 2010

У меня есть этот код:

#include <iostream>
#include <functional>

struct A
{
    int operator()(int i) const {
        std::cout << "F: " << i << std::endl;
        return i + 1;
    }
};

int main()
{
    A a;
    std::tr1::function<int(int)> f = std::tr1::ref(a);
    std::cout << f(6) << std::endl;
}

Цель состоит в том, чтобы передать объект функтора с помощью reference_wrapper таким образом, чтобы избежать ненужных вызовов конструктора копирования. Я ожидаю следующий вывод:

F: 6
7

Он работает правильно с GCC> = 4.4.0, Visual Studio 2008 и с boost, заменяя пространство имен std :: tr1 на boost. Он не работает только с новой Visual Studio 2010, Express Express Beta 2 и Release Candidate.

Исправлены ли эти новые функции C ++ в версии vs2010? Или в коде есть какая-то ошибка или неправильное использование?

Ответы [ 2 ]

11 голосов
/ 11 марта 2010

Я думаю, что нашел причину. Это то, что TR1 3.4/2 говорит о result_of<T(A1, A2, ..., AN)>::type, используемом при определении типа возврата reference_wrapper<T>::operator():

Реализация может определять член типа любым способом, который создает точный тип выражения f (t1, t2, ..., tN) для данных типов. [Примечание: намерение состоит в том, что реализациям разрешено использовать специальные хуки компилятора - конец примечание]

А затем пункт 3:

Если F не является функциональным объектом, определенным стандартной библиотекой, и если либо реализация не может определить тип выражения f (t1, t2, ..., tN), либо если выражение неправильно сформировано, реализация должна использовать следующий процесс для определения члена типа:

  • Если F - это, возможно, cv-квалифицированный тип класса без члена с именем result_type или если typename F::result_type не является типом:
    • Если N = 0 (без аргументов), тип void.
    • Если N> 0, введите typename F::template result<F(T1, T2,..., TN)>::type

Сообщение об ошибке является артефактом попытки применения этих запасных вариантов. Предоставьте typedef для result_type до int, и он должен работать, я думаю. Обратите внимание, что в C++0x все по-другому. Он не использует шаблон result_type или result, поскольку может использовать decltype.

Если с <functional> происходит сбой с MSVC10 в режиме C ++ 0x, он пахнет ошибкой, я бы сказал. Но, может быть, кто-то еще знает, что происходит. Он может (но не гарантирует) работать с <tr1/functional> в режиме C ++ 0x, если этот заголовок выбирает путь decltype вместо ::result_type. Я бы набралdef result_type - таким образом, я думаю, он всегда должен работать независимо от того, используется ли заголовок tr1 или заголовок c++0x.


Также обратите внимание, что boost::tr1 говорит в своей документации, что он не поддерживает оператор вызова функции (но он просто поддерживает неявные преобразования в T&).

1 голос
/ 11 марта 2010

Я сталкиваюсь с подобной проблемой здесь: Предотвращение ненужных копий объектов функтора C ++

Чтобы сделать его компиляцией на MSVC10, мне пришлось извлечь объект функции из std :: unary_function.

...