6

I have the following code:

// string specializations
void foo(const char *a, const char *b);
void foo(const char *a, const std::string &b);
void foo(const std::string &a, const char *b);
void foo(const std::string &a, const std::string &b);

// generic implementation
template<typename TA, typename TB>
void foo(TA a, TA b)
{...}

The problem is that this test case:

char test[] = "test";
foo("test", test);

ends up calling the templated version of foo. Obviously, I can just add a few more overloads with various mixes of non-const parameters, but I want to know: is there's a better way to overload foo such that it is specialized on all const and non-const pairings of strings? One that doesn't require me to hope I haven't missed some permutation of argument types?

7
  • 4
    char *test = "test" isn't something you should do. "test" is const char*. Commented Nov 15, 2012 at 1:17
  • 1
    SFINAE for types that aren't convertible to std::string, or simply make std::string and require callers to convert Commented Nov 15, 2012 at 1:18
  • 3
    Because you also missed that "test" is of type const char[5], not const char*. Commented Nov 15, 2012 at 1:19
  • 2
    @jogojapan, Technically, "test" is const char[5]. Commented Nov 15, 2012 at 1:19
  • Sorry, yes. My point, of course, was the const (and conversion to const char* isn't a problem, while conversion to char * is borderline and only possible because of a deprecated exception in the rules for type casting). Commented Nov 15, 2012 at 1:21

2 Answers 2

3

Thanks to Mooing Duck's suggestion, this is my solution:

// string specialization
void foo(const std::string &a, const std::string &b);

template<typename TA, typename TB>
typename std::enable_if<
    std::is_constructible<std::string, TA>::value &&
    std::is_constructible<std::string, TB>::value
>::type foo(TA a, TB b)
{
    foo(std::string(std::move(a)), std::string(std::move(b)));
}

// generic implementation
template<typename TA, typename TB>
typename std::enable_if<
    !std::is_constructible<std::string, TA>::value ||
    !std::is_constructible<std::string, TB>::value
>::type foo(TA a, TB b)
{...}
Sign up to request clarification or add additional context in comments.

6 Comments

You can std::forward only Universal References.
I would prefer std::is_convertible over std::is_constructible since it also catches conversions not realized by std::string's constructors (like user-defined implicit conversion operators).
It's not incorrect to use std::forward like you do here, but in this instance it may be more straightforward to use std::move directly, since that's what it boils down to.
@ChristianRau std::is_constructible will properly deal with conversion operators. The difference between std::is_constructible<T, Arg>::value and std::is_convertible<Arg, T>::value (mind the order of parameters) is the difference between T t(std::declval<Arg>()); and T t = std::declval<Arg>();.
@LucDanton Ah, thanks for the clarification (when thinking about it, it makes sense that std::is_constructible catches conversion operators, too). In fact it seems std::is_constructible catches even more, since std::is_convertible wouldn't catch explicit constructors. Not sure if this is good or bad here, but I guess it's irrelevant in this case, since calling foo(std::string::allocator_type(), ...) is probably pretty unlikely anyway.
|
0

If I understand your goals properly you could do this

template<typename T1,typename T2 >
void foo(T1, T2)
{
     static_assert(sizeof(T1) == 0,"Did not overload all foo's");
}

template<>
void foo<const char *a, const char *b>()
{
    ... Handle this case
}

... ect ect ect

This has the advantage of you handling every instance you want explicitly while generating a compilation error if you missed one.

2 Comments

Thanks, but I was just typing up my own answer using SFINAE and strings (thanks to Mooing Duck).
Is this really a solution? You'd still need to code many different specializations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.