Reputation: 6068
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
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