Search code examples
c++constructorstdstringenable-if

Disabling a constructor using std::enable_if


My aim is to create my own analogue of std::basic_string but with some additional conditions. I want my AnyString<CharType, Traits> to be convertible from std::basic_string<CharType, AnyOtherTraits, AnyAlloc> but I want to disable this constructor for some CharType such that basic_string<CharType> does not exist (compile).

I tried to do something like that:

    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>&);

And I have ColouredChar, which does not meet the conditions listed inside enable_if_t.

Now, when I'm trying to call the disabled constructor :

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

I do not only get the compile errors from basic_string but also very strange one, telling me that completely different PRIVATE constructor constructor cannot convert its parameter from basic_string.

Is there any way to make these compile errors more readable? Or at least explain whether there's anything here to worry about.


Solution

  • Basic example for constructor restriction using concepts (not your traits)

    #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;
    }