仅在方法退出时使用模板

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);
}

Demo

您可以将 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!");