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