Home > database >  Disabling a constructor using std::enable_if
Disabling a constructor using std::enable_if

Time:11-20

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.

CodePudding user response:

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

CodePudding user response:

just to point out, in addition to exist answer, you don't need to define a concept to use it in require-clause

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

and there is already a std::convertable_to concept

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


fwiw, since you said

I want to disable this constructor for some CharType such that basic_string does not exist

your code fail with string constructor probably simply because you try to create one. it has nothing with ColouredString

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