Question

I have a string class:

#include <stdint.h>

class CString {
public:
    CString() {}
    explicit CString(uint64_t ui64, int width = -1, int base = 10, char fillChar = ' ') {}
    CString(const char * str) {}

    CString arg(const CString& argument) const {return CString();}

    template <typename T>
    inline CString arg(T argument, int width = -1, int base = 10, char fillChar = ' ') const
    {
        return arg(CString(argument, width, base, fillChar));
    }
};

Now, I'm using this class:

void main()
{
    CString str;
    str.arg("123");
}

And get the error:

error C2665: 'CString::CString' : none of the 4 overloads could convert all the argument types
1>          source.cpp(6): could be 'CString::CString(uint64_t,int,int,char)'
1>          while trying to match the argument list '(const char *, int, int, char)'
1>          source.cpp(22) : see reference to function template instantiation 'CString CString::arg<const char*>(T,int,int,char) const' being compiled
1>          with
1>          [
1>              T=const char *
1>          ]

Why doesn't arg(CString&) get called, using the CString(const char *) constructor?

Was it helpful?

Solution 2

When you call

str.arg("123");

the best match is obtained via the function template arg, since CString arg(const CString& argument) requires a conversion to a user defined type. The function template then calls

return arg(CString(argument, width, base, fillChar));

but there is no CString constructor that matches the argument list const char*, int, int, char that you are passing here.

There can be no call to CString(uint64_t, int, int, char) because the conversion from const char* to uint64_t is an invalid conversion. This simplified code sample exhibits the same problem:

#include <cstdint>
void foo(std::uint64_t) {}

int main()
{
  foo("hello");
}

error: invalid conversion from 'const char*' to 'uint64_t {aka long long unsigned int}' [-fpermissive]

foo("hello");

If you were to comment out the member function template arg, then CString arg(const CString& argument) would be called, via the implicit conversion from const char* to CString.

OTHER TIPS

Note: This answers the original question, before it was changed into a different one.

why doesn't template arg overload work?

Because it requires at least two arguments, and you are passing one.

template <typename T>
inline CString arg(T argument, int width, int base = 10, char fillChar = ' ')
{ ... }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top