仅在方法退出时使用模板
Using the template only if the method exits
如果索引容器 (map,set) 调用 tool::exists_in
并且具有查找方法,它将调用第一个方法,谁能帮我完成这段代码。如果没有,调用第二种方法。
namespace tools {
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
->decltype(source->find())
{
return source.find() != source.end();
}
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
{
return std::find(source.begin(), source.end(), item)
!= source.end();
}
}
int main()
{
std::set<int> vector= { 1, 2, 3 };
std::vector<int> set = { 1, 2, 3 };
std::cout<<tools::exists_in(vector, 1);///should execute the first **tools::exists_in** method
std::cout<<tools::exists_in(set, 1);///should execute the second **tools::exists_in** method
}
首先,第一个函数应该是
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
-> decltype(source.find() != source.end())
// ^^^^^^^^^^^^^^^^
{
return source.find() != source.end();
}
具有正确的 return 类型。
然后你可以在重载之间使用一些“优先级”(最佳匹配)作为int
与...
.
我更喜欢具有继承性的显式(甚至可以无限优先级完成):
struct low_priority {};
struct high_priority : low_priority {};
template<class TSource, class Ty>
auto exists_in(high_priority, const TSource &source, const Ty &item)
-> decltype(source->find(item) != source.end())
{
return source.find(item) != source.end();
}
template<class TSource, class Ty>
auto exists_in(low_priority, const TSource &source, const Ty &item)
{
return std::find(source.begin(), source.end(), item) != source.end();
}
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
{
return exists_in(high_priority{}, source, item);
}
您可以将 has_find
与 SFINAE 一起使用以 enable/disable 重载,具体取决于 TSource::find 是否存在(参见 Live 示例):
namespace tools {
template <typename T>
struct has_find
{
// use expression sfinae instead of obvious
// template <typename C> static char test(decltype(&C::find)); - which doesn't seem to work correctly in this case
template <typename C> static char test( decltype(std::declval<C>().find(typename C::value_type{}))* );
template <typename C> static int test(...);
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
template<class TSource, class Ty>
std::enable_if_t<has_find<TSource>::value, bool>
exists_in(const TSource &source, const Ty &item)
{
return source.find(item) != source.end();
}
template<class TSource, class Ty>
std::enable_if_t<! has_find<TSource>::value, bool>
exists_in(const TSource &source, const Ty &item)
{
return std::find(source.begin(), source.end(), item) != source.end();
}
}
编辑:
添加静态断言以验证 has_find
是否正常工作:
using Set = std::set<int>;
using Vector = std::vector<int>;
using tools::has_find;
static_assert(has_find<Set>::value == true, "Error: Set::find not found!");
static_assert(has_find<Vector>::value == false, "Error: Vector::find found!");
如果索引容器 (map,set) 调用 tool::exists_in
并且具有查找方法,它将调用第一个方法,谁能帮我完成这段代码。如果没有,调用第二种方法。
namespace tools {
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
->decltype(source->find())
{
return source.find() != source.end();
}
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
{
return std::find(source.begin(), source.end(), item)
!= source.end();
}
}
int main()
{
std::set<int> vector= { 1, 2, 3 };
std::vector<int> set = { 1, 2, 3 };
std::cout<<tools::exists_in(vector, 1);///should execute the first **tools::exists_in** method
std::cout<<tools::exists_in(set, 1);///should execute the second **tools::exists_in** method
}
首先,第一个函数应该是
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
-> decltype(source.find() != source.end())
// ^^^^^^^^^^^^^^^^
{
return source.find() != source.end();
}
具有正确的 return 类型。
然后你可以在重载之间使用一些“优先级”(最佳匹配)作为int
与...
.
我更喜欢具有继承性的显式(甚至可以无限优先级完成):
struct low_priority {};
struct high_priority : low_priority {};
template<class TSource, class Ty>
auto exists_in(high_priority, const TSource &source, const Ty &item)
-> decltype(source->find(item) != source.end())
{
return source.find(item) != source.end();
}
template<class TSource, class Ty>
auto exists_in(low_priority, const TSource &source, const Ty &item)
{
return std::find(source.begin(), source.end(), item) != source.end();
}
template<class TSource, class Ty>
auto exists_in(const TSource &source, const Ty &item)
{
return exists_in(high_priority{}, source, item);
}
您可以将 has_find
与 SFINAE 一起使用以 enable/disable 重载,具体取决于 TSource::find 是否存在(参见 Live 示例):
namespace tools {
template <typename T>
struct has_find
{
// use expression sfinae instead of obvious
// template <typename C> static char test(decltype(&C::find)); - which doesn't seem to work correctly in this case
template <typename C> static char test( decltype(std::declval<C>().find(typename C::value_type{}))* );
template <typename C> static int test(...);
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
template<class TSource, class Ty>
std::enable_if_t<has_find<TSource>::value, bool>
exists_in(const TSource &source, const Ty &item)
{
return source.find(item) != source.end();
}
template<class TSource, class Ty>
std::enable_if_t<! has_find<TSource>::value, bool>
exists_in(const TSource &source, const Ty &item)
{
return std::find(source.begin(), source.end(), item) != source.end();
}
}
编辑:
添加静态断言以验证 has_find
是否正常工作:
using Set = std::set<int>;
using Vector = std::vector<int>;
using tools::has_find;
static_assert(has_find<Set>::value == true, "Error: Set::find not found!");
static_assert(has_find<Vector>::value == false, "Error: Vector::find found!");