Явный конструктор по-прежнему допускает неявное преобразование

Я делаю набросок небольшого универсального шаблона типа-оболочки в C ++ 14, который предназначен для включения, отключения или расширения интерфейса нижележащего типа с помощью миксинов.

Вот код этой обертки (немного урезанный):

namespace detail {
/// Helper template that is forwarded to the mixins used
/// for the extension of wrapper<•> in order to enable
/// access to the actual type `Derived`
template <typename Derived>
struct Cast {
using type = Derived;

template <typename T>
static constexpr Derived& self(T* self) { return *static_cast<Derived*>(self); }

template <typename T>
static constexpr Derived const& self(T const* self) { return *static_cast<Derived const*>(self); }
};

/// This helper template is used to derive from all the Mixins
/// one after another, making sure the constructor is mixed in as well:
template <typename Cast, typename T,template <typename...> class...Mixins>
struct wrapper_impl;

template <typename Cast, typename T,template <typename...> class First, template <typename...> class...Rest>
struct wrapper_impl<Cast, T, First, Rest...>
: First<Cast, T>
, wrapper_impl<Cast, T, Rest...>
{
using First<Cast, T>::First;
using wrapper_impl<Cast, T, Rest...>::wrapper_impl;
};

template <typename Cast, typename T, template <typename...> class First>
struct wrapper_impl<Cast, T, First>
: First<Cast, T>
, wrapper_impl<Cast, T>
{
using First<Cast, T>::First;
using wrapper_impl<Cast, T>::wrapper_impl;
};

template <typename Cast, typename T>
struct wrapper_impl<Cast, T>  {
};
}template <typename T, typename Tag, template <typename...> class...Mixins>
class wrapper : public detail::wrapper_impl<detail::Cast<wrapper<T,Tag,Mixins...>>, T, Mixins...> {
public:
using value_type = T;
using detail::wrapper_impl<detail::Cast<wrapper<T,Tag,Mixins...>>, T, Mixins...>::wrapper_impl;

T& get() { return *reinterpret_cast<T*>(&m_buffer); }
T const& get() const { return *reinterpret_cast<T const*>(&m_buffer); }

template <typename...Args>
void construct(Args&&...args) {
new (&m_buffer) T(std::forward<Args>(args)...);
}

void destruct() {
get().~T();
}

~wrapper() {
destruct();
}

private:
std::aligned_storage_t<sizeof(T), alignof(T)> m_buffer;;
};

Теперь я могу смешать в какой-то форме конструкции T используя следующий миксин-шаблон:

template <typename T>
struct constructor_from {
template <typename Cast, typename U>
struct mixin {
explicit mixin(T const& value) {
Cast::self(this).construct(U{value});
}
};
};

Пока это работает хорошо, например Я могу завернуть int вот так:

using my_int = wrapper<int, struct Tag, constructor_from<int>::mixin>;
my_int instance{42};

Смотрите полный код здесь на godbolt. Тем не менее, я хочу отключить нежелательные неявные преобразования, поэтому я отметил конструктор constructor_from::mixin как explicit, Но неожиданно следующее, по-видимому, все еще компилируется без ошибок на clang-5.0.0 (см. На компилятор-исследователь):

using my_int = wrapper<int, struct Tag, constructor_from<int>::mixin>;
my_int instance{4.2};
  • Это ошибка в clang-5.0.0? Это, похоже, компилируется с ожидаемой неудачей в НКУ-7,3.
  • Если это не ошибка, я делаю что-то необоснованное (неопределенное, неуказанное, …) здесь, которое объясняет, почему он должен компилироваться, несмотря на explicit конструктор на clang-5.0.0? Или, может быть, я неправильно понимаю, как работает наследование конструктора?

Поскольку @someprogrammerdude имеет указатель, возможно, я неправильно понимаю explicit строительство. Тем не менее, я до сих пор не понимаю, почему приведенный выше код должен компилироваться, в то время как этот не:

struct foo {
explicit foo(int) {}
};

struct bar : foo {
using foo::foo;
};

int main() {
bar instance{4.2};
}

Было бы замечательно, если бы кто-то мог указать мне на соответствующие разделы в стандарте c ++, которые разрешают конструкцию в случае моего wrapper, но предотврати это в этом случае здесь

3

Решение

Задача ещё не решена.

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector