Search code examples
c++templatestypename

No matching call for function templated parameter is used


This is a follow up to my previous question about templates: Unable to use typedef definied in templated structure

When building the following piece of code, the compiler doesn't find the implementation of function, and outputs the the following error.

./test.cpp: In function ‘int main()’:
./test.cpp:30:13: error: no matching function for call to ‘function(BUFFER_T<128>::FRAME_DATA)’
   30 |     function(buffer.FrameData);
      |     ~~~~~~~~^~~~~~~~~~~~~~~~~~
./test.cpp:20:6: note: candidate: ‘template<unsigned int BufferSize> bool function(typename BUFFER_T<BufferSize>::FRAME_DATA&)’
   20 | bool function(typename BUFFER_T<BufferSize>::FRAME_DATA& FrameBufferInput)
      |      ^~~~~~~~
./test.cpp:20:6: note:   template argument deduction/substitution failed:
./test.cpp:30:13: note:   couldn’t deduce template parameter ‘BufferSize’
   30 |     function(buffer.FrameData);
      |     ~~~~~~~~^~~~~~~~~~~~~~~~~~

How can I fix this error?

#include <stdint.h>


template<uint32_t BufferSize>
struct BUFFER_T
{
        static constexpr uint32_t   LENGTH_FRAME_NUMBER = 4u;
        static constexpr uint32_t   LENGTH_FRAME_OFFSET = 4u;
        static constexpr uint32_t   LENGTH_FRAME_CRC    = 4u;
        static constexpr uint32_t   LENGTH_FRAME_DATA   = BufferSize - LENGTH_FRAME_NUMBER - LENGTH_FRAME_OFFSET - LENGTH_FRAME_CRC;

        typedef uint8_t             FRAME_DATA  [LENGTH_FRAME_DATA];

        FRAME_DATA                  FrameData;
};


template<uint32_t BufferSize>
bool function(typename BUFFER_T<BufferSize>::FRAME_DATA& FrameBufferInput)
{
    return true;
}


int main()
{
    BUFFER_T<128u> buffer{};

    function(buffer.FrameData);

    return 0;
}

Solution

  • BufferSize can't be deduced because it's in a non-deduced context.

    You could however make sure that you actually got an array of uint8_t as input:

    template <uint32_t LENGTH_FRAME_DATA>
    bool function(uint8_t(&FrameBufferInput)[LENGTH_FRAME_DATA]) {
        // std::cout << LENGTH_FRAME_DATA << '\n';
        return true;
    }
    

    It will however not make sure that the array belongs to a BUFFER_T instance and BufferSize and all the member constants are unavailable.


    If you need access to the constants and want to make sure the buffer actually belongs to a BUFFER_T, you could simply take a BUFFER_T& instead:

    template<uint32_t BufferSize>
    bool function(BUFFER_T<BufferSize>& buff) {
        auto& FrameBufferInput = buff.FrameData;
        
        return true;
    }
    

    ... and then call it with: function(buffer);.