11

У меня есть этот код:Visual Studio 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, таким образом, чтобы избежать ненужных звонков от копирования costructor. Я ожидаю, что следующий вывод:

F: 6 
7 

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

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

+0

Как это не работает? – UncleBens

+0

@litb: Я думаю, что OP имеет проблемы с использованием класса шаблонов 'std :: tr1 :: ref' и * not * boost на VS2010. – dirkgently

+0

Вот выход сборки VS2010: http://pastebin.com/YQf4Qe8W –

ответ

11

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

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

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

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

  • Если F является, возможно, классом класса cv, без memb er по имени result_type или если typename F::result_type не является типом:
    • Если N = 0 (без аргументов), тип недействителен.
    • Если 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. Я бы сделал typedef result_type - так я думаю, что он всегда должен работать независимо от того, используется ли заголовок tr1 или заголовок c++0x.


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

+1

Да, это исправить проблему: D Это жаль для vs2010 для этой регрессии по сравнению с предыдущей версией 2008 года ... В последнем проекте строго требуется, чтобы компилятор автоматически распознавал тип возврата. http://www.open-std.org/JTC1/SC22/ WG21/docs/papers/2009/n3000.pdf Пункт 20.7.4 –

1

я сталкиваюсь с подобной проблемой здесь: Prevent unnecessary copies of C++ functor objects

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