Следующий код не компилируется с clang 3.1 с использованием libc ++ (не знаю версию, текущую, которая поставляется с Xcode). Он отлично работает с другими стандартными библиотеками. Есть ли ошибка в моем коде, или это ошибка в libc ++?
#include <map>
#include <string>
using namespace std;
struct A {
A(const map<int, A>& m) {}
};
struct B {
map<string, A> m;
};
Я вижу ошибку в <utility>
:
/usr/lib/c++/v1/utility:241:64: No member named 'value' in 'std::__1::is_nothrow_copy_constructible<A>'
Я попытался выделить это дальше, но это минимальный пример, который я нашел. Интересно, когда я заменю string
от int
во второй карте это работает (также когда я заменяю int
от string
на первой карте):
map<string, A> m; // Does not work
map<int, A> m; // Works
Это не совсем ошибка, и я объясню вам, почему:
В 1997 году, незадолго до завершения работы над стандартом C ++, комитет по стандартизации получил запрос: возможно ли создавать стандартные контейнеры с неполными типами? Комитету понадобилось время, чтобы понять вопрос. Что бы это вообще значило, и с какой стати вы захотите это сделать? В конце концов комитет разработал это и придумал ответ на вопрос. (Чтобы вам не приходилось пропускать до конца, ответ — «нет».) Но вопрос гораздо интереснее, чем ответ: он указывает на полезную и недостаточно обсужденную технику программирования. Стандартная библиотека не поддерживает эту технику напрямую, но они могут сосуществовать.
Когда вы декларируете const std::map<int, A>&
, A
все еще неполный, и стандарт не заставляет исполнителей предоставлять поддержку для неполных типов, так что если вам это действительно нужно, и у вас есть возможность использовать boost
, вы можете изменить свой контейнер и использовать boost::container
вместо стандартного контейнера в компиляторах, которые не поддерживают это.
Других решений пока нет …