Отключение конструктора с помощью std::enable_if

Моя цель — создать свой аналог std::basic_string, но с некоторыми дополнительными условиями. Я хочу, чтобы мой AnyString<CharType, Traits> можно было преобразовать из std::basic_string<CharType, AnyOtherTraits, AnyAlloc>, но я хочу отключить этот конструктор для некоторого CharType, такого, что basic_string<CharType> не существует (компилируется).

Я пытался сделать что-то вроде этого:

    template<typename OtherTraits, typename Alloc, typename = 
        std::enable_if_t<!std::is_array_v<char_type> && 
        std::is_trivial_v<char_type>                 && 
        std::is_standard_layout_v<char_type>>>
    AnyString(const std::basic_string<char_type, OtherTraits, Alloc>&);

И у меня есть ColouredChar, который не соответствует условиям, указанным внутри enable_if_t.

Теперь, когда я пытаюсь вызвать отключенный конструктор:

std::basic_string<ColouredChar> de("string"_purple);
ColouredString d(de);

Я получаю не только ошибки компиляции от basic_string, но и очень странную, сообщающую мне, что совершенно другой конструктор ЧАСТНОГО конструктора не может преобразовать свой параметр из basic_string.

Есть ли способ сделать эти ошибки компиляции более читабельными? Или хотя бы объяснить, есть ли здесь повод для беспокойства.

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

Sam Varshavchik 19.11.2022 19:48

Я рассматривал концепции, но понятия не имею, как их здесь применить.

Capy Maths 19.11.2022 19:50

На самом деле ваше требование странное, вы создаете std::basic_string<ColouredChar> de("string"_purple); так оно и есть, но вы думаете, что его не существует?

apple apple 19.11.2022 22:13
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
2
3
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Базовый пример ограничения конструктора с использованием концепций (а не ваших трейтов)

#include <type_traits>
#include <string>

// declare your own concept
template<typename type_t>
concept my_concept = std::is_convertible_v<type_t, std::string>; // just a demo concept
    
class ColouredString
{
public:
    // then you can limit your constructor to types satisfying that concept
    ColouredString(const my_concept auto& /*arg*/)
    {
    }

    ~ColouredString() = default;
};


int main()
{
    // ColouredString str{ 1 };
    ColouredString str{ "hello world!" };

    return 0;
}

Просто чтобы указать, что в дополнение к существующему ответу вам не нужно определять концепцию, чтобы использовать ее в предложении require

class ColouredString{
public:
    template<typename T>
    requires (std::is_convertible_v<T, std::string>)
    ColouredString(const T&){}
};

И уже есть концепция std::convertable_to

class ColouredString{
public:
    ColouredString(const std::convertible_to<std::string> auto&){}
};


Кстати, раз ты сказал

Я хочу отключить этот конструктор для некоторого CharType, так что basic_string не существует

Ваш код не работает с конструктором string, вероятно, просто потому, что вы пытаетесь его создать. это не имеет ничего общего с ColouredString

std::basic_string<ColouredChar> de("string"_purple); // it already fail here
ColouredString d(de); 

Ты прав. Мы не можем инициализировать ColoredString без создания std::basic_string с помощью описанного конструктора. std::basic_string сам генерирует ошибки компиляции, когда мы пытаемся его создать. Но проблема была в нечитаемости текстов ошибок компиляции - об этом я и спрашивал. Спасибо.

Capy Maths 19.11.2022 22:21

@CapyMaths, тогда ограничение на конструктор ColouredString не поможет.

apple apple 19.11.2022 22:22

Другие вопросы по теме