2015-12-17 3 views
3

Мне нужно использовать старый код устаревшего кода, который использует std::tr1::shared_ptr. Заголовок, который мне нужно включить, имеет как #include <tr1/memory>, так и #include <tr1/functional>. В моем коде я хочу использовать std::function и std::bind, так как наш компилятор поддерживает их.Смешивание std :: tr1 :: shared_ptr с std :: function/std :: bind вызывает ошибки компилятора с новым gcc

Это прекрасно работает с gcc 4.6.3 и 4.7.3. В 4.9.2, 5.1.x и 5.2.0 это приводит к ошибке компилятора. Кажется, это происходит из-за <tr1/functional> -include.

я написал небольшой пример, который воспроизводит эту проблему:

#include <tr1/memory> 
#include <functional> 
#include <tr1/functional> 

struct Foo { 
    void test(std::tr1::shared_ptr<int> i) {} 
}; 

int main() { 
    Foo f; 
    std::function<void(std::tr1::shared_ptr<int>)> func = std::bind(&Foo::test, f, std::placeholders::_1); 

    return 0; 
} 

GCC-4.6.3, без #include <tr1/functional>, компилирует КИ. Протестировано на моей локальной машине.

gcc-4.6.3, с #include <tr1/functional>, компилирует ОК. Протестировано на моей локальной машине.

НКУ-5,1, без #include <tr1/functional>, компилирует OK: http://ideone.com/XrkAXT

НКУ-5,1, с #include <tr1/functional>, ошибка компилятора: http://ideone.com/sRWQLn

Я не использую любой std::tr1::function или std::tr1::bind вообще, и единственное, Я использую из устаревшего кода объект std::tr1::shared_ptr.

Почему #include <tr1/functional> влияет на не-tr1 std::function/std::bind? Или что здесь происходит?

Редактировать: Согласно GNU C++ Library Manual, Chapter 3: «Частным случаем второго правила является смешивание объектов TR1 и C++ 11. Возможно, хотя и не особенно разумным, включить как версию TR1, так и C + +11 версия заголовка в той же системе перевода «

+1

Clang несколько более полезен и сообщает о [двусмысленности] (http://coliru.stacked-crooked.com/a/42b7d781e2829fb7). Я собираюсь догадаться о ADL. –

+0

не так, потому что вы включили как функциональные, так и tr1/functional? – sop

+1

@sop См. Мое редактирование. – gurka

ответ

6

Было внесено изменение в стандарт, требующий реализации для ограничения конструктора std::function, чтобы он не был конвертирован со всего, что под солнцем, но только из реальных вызовов, поэтому libstdC++ вычисляет возвращаемый тип с помощью:

template<typename _Functor> 
using _Invoke = decltype(__callable_functor(std::declval<_Functor&>()) 
         (std::declval<_ArgTypes>()...)); 

и использует его в SFINAE. Выражение SFINAE означает, что если выражение вызова не компилируется, конструктор преобразования удаляется из набора перегрузки.

Проблема с этим __callable_functor. Его задача - обернуть указатель-к-членам, чтобы они могли использоваться с синтаксисом нормального вызова функции. И это зарезервированное имя, поэтому никто не должен его использовать ... ну, кроме других компонентов стандартной библиотеки. У нас есть std::__callable_functor в <functional> и std::tr1::__callable_functor в <tr1/functional>. И поскольку std::tr1 является ассоциированным пространством имен (спасибо за использование std::tr1::shared_ptr<int> в подписи Foo::test), вы получите двусмысленность.

Редактировать: сообщается как bug 68995.

Смежные вопросы