Reputation: 42379
#include <string>
#include <type_traits>
using namespace std;
template
<
typename CharT,
template<typename> class Traits,
template<typename> class Allocator,
typename RightT,
typename StringT = basic_string
<
CharT,
Traits<CharT>,
Allocator<CharT>
>
>
enable_if_t
<
is_constructible<StringT, RightT>::value,
StringT&
>
operator <<(StringT& lhs, const RightT& rhs)
{
return lhs.append(rhs);
}
int main()
{
string s1, s2;
s1 << s2; // compilation error!
return 0;
}
My compiler is VS 2015 Update 3. The compilation error message is:
error : invalid operands to binary expression ('string' (aka 'basic_string, allocator >') and 'string')
Why does it not work as expected?
Upvotes: 1
Views: 175
Reputation: 3877
Did the compiler give you any more info than that single line? Something like:
26:1: note: template argument deduction/substitution failed:
35:11: note: couldn't deduce template parameter 'CharT'
If you replace
operator <<(StringT & lhs, const RightT& rhs)
with
operator <<(basic_string<CharT, Traits<CharT>, Allocator<CharT>>& lhs, const RightT& rhs)
it compiles.
Basically you are putting the cart before the horse. You can use template args to form a default template arg (StringT = ...
) if you already know the template args. You can't use the default to determine the args.
If you want to support both basic_string
and other/custom strings, you may need to write two specializations or something.
Or realize what your template requirements really are - you don't require Constructible, you require "Appendable", so SFINAE on that, and ignore whether it is a basic_string or MyCustomString - it doesn't matter; the only thing that matters is whether lhs.append(rhs)
works (and, uh, maybe figure out its return type as well...)
Upvotes: 4