Проблема с is_copy_constructible

Должна ли черта типа справиться с такими случаями, как std::vector < std::unique_ptr <int> > и обнаружить, что это не копируемый конструкт?

Вот пример на https://ideone.com/gbcRUa (работает g ++ 4.8.1)

#include <type_traits>
#include <vector>
#include <iostream>
#include <memory>

int main()
{
// This prints 1, implying that it's copy constructible, when it's clearly not
std::cout << std::is_copy_constructible< std::vector<std::unique_ptr<int> > >::value << std::endl;
return 0;
}

Если это правильное поведение для is_copy_constructibleЕсть ли способ обнаружить, что конструкция копии плохо сформирована? Ну, кроме того, что он не компилируется.

11

Решение

Это из-за недостатка в дизайне 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>> : test<T> {}

что дает нам:

template<typename T>
using smart_is_copy_constructible = smart_test< std::is_copy_constructible, T >;

и подобное для < а также ==, Я могу добавить больше специализаций, когда столкнусь с большим количеством типов контейнеров, которые действительно должны перенаправить свои свойства в свои данные, или я мог бы написать более интересный контейнер-тест SFINAE и выполнить traits, извлечь базовый тип-значение и отправить вопрос в тест. на типе значения.

Но по моему опыту, я в основном в конечном итоге делать эти тесты на std::vector,

9

Другие решения

В таблице 49 стандарта C ++ 11 перечислены условия, которым должен соответствовать класс is_copy_constructable<T>::value чтобы быть правдой, и это, к сожалению, не так много

is_constructable<T, const T&>::value является true

Так что если std::vector<T> имеет конструктор копирования, он проходит тест.

3

По вопросам рекламы [email protected]