1

I'll just get right down to it: Why doesn't line 38 implicitly convert to char (&)[32]?

template <size_t StringSize>
struct StringT
{
private:
    char mChars[StringSize];

public:
    // Note: CharArray can decay to char*.
    typedef char (&CharArray)[StringSize];

    CharArray array() { return mChars; }
    operator CharArray() { return mChars; }
    operator const CharArray() const { return mChars; }
};

#include <iostream>

template<size_t Size>
void f(char (&array)[Size])
{
    std::cout << "I am char array with size " << Size << "\n";
}

int main()
{
    StringT<32> someText;

    // Conversion through method compiles.
    f(someText.array());

    // Explicit conversion compiles.
    f((StringT<32>::CharArray)someText);

    // Implicit conversion fails:
    // source_file.cpp(38): error C2672: 'f': no matching overloaded function found
    // source_file.cpp(38): error C2784: 'void f(char (&)[Size])': could not deduce template argument for 'char (&)[Size]' from 'StringT<32>'
    // source_file.cpp(19): note: see declaration of 'f'
    f(someText);
}

This is currently just a small experiment, but the implicit conversion is highly neccessary if StringT<> is to serve the intended purpose - replacing most of the char arrays in a codebase I am working in.

Thanks in advance.

  • isn't your compiler complaining for operator const CharArray() const { return mChars; } 'const' qualifier on reference type 'CharArray' (aka 'char (&)[StringSize]') has no effect – Hariom Singh Aug 24 '17 at 21:30
  • The issue comes from `f()` being templated. `void f(char (&array)[32])` would work fine. I'll try and lookup the actual rule for this. –  Aug 24 '17 at 21:33
  • Possible duplicate of [C++ implicit type conversion with template](https://stackoverflow.com/questions/9787593/c-implicit-type-conversion-with-template) –  Aug 24 '17 at 21:34
  • To get at match you would have to apply the conversion operator first and then do the template deduction. That's not the order things happen (unless you code it explicitly). – Bo Persson Aug 24 '17 at 21:35
  • @Frank That sounds like it's the core of the issue, but is there any way to go around it in some way? Btw, while the the suggested dublicate is interesting, it seemingly describes the issue in regards of different types in deduction, but I could not find my particular issue fully explained. Maybe i am misunderstanding something? – Emanuel Strömgren Aug 24 '17 at 21:47
  • @BoPersson That makes sense. Is it completely impossible to somehow get line 38 to work? Can I somehow make the compiler try the implicit conversion rule before failing the template deduction? – Emanuel Strömgren Aug 24 '17 at 21:48

1 Answers1

1

I understand this is for a refactoring task, and it's probably not feasible in your scenario, however:

If you want to maintain the interface as shown in your main() function, you will need to create a templated overload of f() that will resolve directly to StringT<Size> before any implicit conversion is applied.

template<size_t Size>
void f(StringT<Size>& v)
{
    f(v.array());
}

N.B. I made it non-const because your original code has some weird const handling, and I wanted the sample to compile as a drop-in to your OP.

  • Hmm, for some reason I didn't think of doing it like this. This is probably the most sensible solution for my case actually. Thank you for your answer! – Emanuel Strömgren Aug 24 '17 at 22:01
  • If you go down that road, you may as well get rid of the implicit conversion operator, and invoke an accessor in the overloaded function. Implicit conversions should be avoided in general. –  Aug 24 '17 at 22:03