André Fratelli
André Fratelli

Reputation: 6068

no matching member function for call to 'insert'

I have the following method declaration on a basic_buffer class:

const_iterator insert(const_iterator position, typename argument<value_type>::type val)

Notice the type of the second argument. I often use this argument traits that basically decides whether the argument should be passed by copy or by reference when receiving template arguments. In this case, value_type is a typedef of the template argument T. For instance, fundamental types should be passed by copy instead of const reference. Here's the implementation:

template <typename T> struct argument
{
    typedef std::conditional<std::is_fundamental<T>::value || std::is_pointer<T>::value, const T, const T &> type;
};

Notice how fundamental and pointer types evaluate to const T and other types evaluate to const T &. This has been working great so far.

Now consider the following function:

template <class T>
void foo()
{
    typedef basic_buffer<T> _storage_type;
    typedef typename _storage_type::value_type _value_type;

    _value_type value = 0;
    _storage_type _storage;

    _storage.insert(_storage.end(), value);
}

Several details are omitted. This is what I get:

error: no matching member function for call to 'insert'
    _storage.insert(_storage.end(), value);
    ~~~~~~~~~^~~~~~

What surprises me is this overload version not being matched:

note: candidate function not viable: no known conversion from '_value_type' (aka 'unsigned char') to 'typename argument<value_type>::type' (aka 'conditional<std::is_fundamental<unsigned
      char>::value || std::is_pointer<unsigned char>::value, const unsigned char, const unsigned char &>') for 2nd argument
    const_iterator insert(const_iterator position, typename argument<value_type>::type val)

To make matters even more confusing, if I cast value to _value_type (that, notably, is already its type) it works:

_storage.insert(_storage.end(), static_cast<_value_type>(value));

So I can solve this by casting value, but rather not. What is happening here?

Upvotes: 1

Views: 2594

Answers (1)

NathanOliver
NathanOliver

Reputation: 180955

You have

typedef std::conditional<std::is_fundamental<T>::value || std::is_pointer<T>::value, const T, const T &> type;

So type is a std::conditional<std::is_fundamental<T>::value || std::is_pointer<T>::value, const T, const T &>

When you call

_storage.insert(_storage.end(), value);

It is trying to convert value to a std::conditional<std::is_fundamental<T>::value || std::is_pointer<T>::value, const T, const T &>

You need to add ::type to the conditional to get the resulting type from the condition.

typedef std::conditional<std::is_fundamental<T>::value || std::is_pointer<T>::value, const T, const T &>::type type;

Upvotes: 3

Related Questions