Ответ 1
Это связано с недостатком конструкции std::vector
. std::vector
определяет конструкцию копирования, даже если он не сможет скомпилироваться, и полагается, что пользователи std::vector
не будут вызывать метод, если он не скомпилируется.
Альтернативный дизайн - SFINAE блокирует вызов метода, если тип, содержащийся в vector
, не имеет конструктора копирования. Тем не менее, std::vector
был разработан до разработки современных методов SFINAE.
Возможно, он может быть встроен в новую итерацию C++, так как будет очень мало кода, который может сломаться. Нельзя сказать, что ни один код не сломается, потому что у вас может быть код, основанный на том факте, что std::is_copy_constructible< std::vector< no_copy_type > >
является std::true_type
, или эквивалентные выражения, но это довольно странная зависимость.
Вдобавок к тому, что std::vector
старше техник SFINAE, которые могут решить эту проблему, делать это с SFINAE довольно грязно (так как SFINAE - грязная техника). Новая концепция-облегченная версия, предложенная для C++ 1y, может сделать ее более чистой и более заманчивой для включения в новую итерацию языка.
Моя работа вокруг, когда у меня есть контейнер, который должен знать, можно ли безопасно скопировать, сравнить и упорядочить содержащийся объект, состоит в том, чтобы специализироваться для std::vector
в классе пользовательских свойств и использовать значение класса пользовательских свойств в Содержащийся тип. Это лоскутное и довольно навязчивое решение.
template<template<typename>class test, typename T>
struct smart_test : test<T> {};
template<template<typename>class test, typename T, typename A>
struct smart_test<test, std::vector<T,A>> : smart_test<T> {};
что дает нам:
template<typename T>
using smart_is_copy_constructible = smart_test< std::is_copy_constructible, T >;
и аналогичные для <
и ==
. Я могу добавить больше специализаций, когда столкнусь с большим количеством типов контейнеров, которые действительно должны перенаправить свои свойства в свои данные, или я мог бы написать более интересный контейнер-тест SFINAE и выполнить traits, извлечь базовый тип-значение и отправить вопрос в тест. на типе значения.
Но по моему опыту, я в основном в итоге выполняю эти тесты на std::vector
.
Обратите внимание, что поскольку к вектору c++11 были добавлены правила "участвует в разрешении перегрузки", это говорит о стандартах для тестов "do SFINAE".