Reputation: 2309
#include "stdafx.h"
#include <algorithm>
class MyClass {
};
template <typename C, typename V, typename Enable = void>
static bool Contains(const C& container, const V& value) {
auto iter = std::find(container.begin(), container.end(), value);
auto result = (iter != container.end());
return result;
}
template <typename C, typename V,
typename std::enable_if<std::is_same<std::reference_wrapper<const V>, typename C::value_type>::value, bool>::type>
static bool Contains(const C& container, const V& value) {
auto iter = std::find_if(container.begin(), container.end(), [&](auto& aValue) {
return (aValue.get() == value);
});
auto result = (iter != container.end());
return result;
}
int main() {
const MyClass a;
auto container = {
std::reference_wrapper<const MyClass>(a),
};
Contains(container, a);
return 0;
}
Compiler: VC++2015U3
Compile error:
Severity Code Description Project File Line Suppression State Error C2678 binary '==': no operator found which takes a left-hand operand of type 'const std::reference_wrapper' (or there is no acceptable conversion) ConsoleApplication1 c:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility 3258
It runs into the first implementation rather than the second one.
Any idea about this?
Upvotes: 0
Views: 581
Reputation: 66210
Maybe you need also an operator==()
for MyClass
but, to solve the specialization problem, I think is better to use an explicit specialization
template <template <typename...> class C, typename V>
static bool Contains (C<std::reference_wrapper<V const>> const & container,
V const & value) {
auto iter = std::find_if(container.begin(), container.end(), [&](auto& aValue) {
return (aValue.get() == value);
});
auto result = (iter != container.end());
return result;
}
instead of SFINAE.
Because if you also make SFINAE works to enable the reference-wrapper-container version, by example
template <typename C, typename V>
static std::enable_if_t<std::is_same<std::reference_wrapper<const V>,
typename C::value_type>::value, bool>
Contains (const C& container, const V& value)
both versions of Contains()
function matches the call
Contains(container, a);
and no one is preferred.
Upvotes: 1
Reputation: 37586
You need to define operator ==
to compare class instances:
bool operator ==(MyClass const & left, MyClass const & right) { return false; }
This operator will be invoked by std::find
and std::find_if
algorithms (rather inside of lambda return (aValue.get() == value);
in the second case).
Upvotes: 1