简体   繁体   中英

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.

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

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 astd::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); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM