lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] Difficulty writing a generic contains() function template


From: Greg Chicares
Subject: [lmi] Difficulty writing a generic contains() function template
Date: Tue, 04 May 2010 17:08:08 +0000
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

I'm stuck here ['icon_monger.cpp', line 45]:

    // SOMEDAY !! Write a "contains.hpp" header that implements this
    // function for every standard container as well as std::string.
    // Rationale: this usage represents half of our find() calls, and
    // the idiom is verbose.
    template<typename Key, typename Compare, typename Allocator>
    bool contains(std::set<Key,Compare,Allocator> const& c, Key const& k)
    {
        return c.end() != c.find(k);
    }

What's the best way to proceed?

I could write one such function for each container, but that's tasteless.

I thought the following was clever, until I added std::set to the unit
test and realized std::set::key_type is the same as std::set::value_type.

#include <algorithm> // std::find()
#include <cassert>
#include <map>
#include <set>
#include <string>
#include <vector>

  // If a class has 'npos', assume it should behave like std::string.
template<typename T>
bool contains(T const& container, T const& element, typename T::size_type = 
T::npos)
{
    return T::npos != container.find(element);
}

template<typename T>
bool contains(T const& container, typename T::traits_type::char_type const* 
element)
{
    return T::npos != container.find(element);
}

  // If a class has 'key_type', assume it should behave like an associative 
container.
template<typename T>
bool contains(T const& container, typename T::key_type const& element)
{
    return container.end() != container.find(element);
}

  // Otherwise, std::find() is the best we can do.
template<typename T>
bool contains(T const& container, typename T::value_type const& element)
{
    return container.end() != std::find(container.begin(), container.end(), 
element);
}

int main()
{
    std::string s("etaoin shrdlu");
    std::string t("alpha omega");
    assert( contains(s, s));
    assert(!contains(s, t));
    assert( contains(s, "eta"));
    assert(!contains(s, "epsilon"));
#if 1 // It compiles if I change this to '#if 0'...
    std::set<std::string> u;
    u.insert("one");
    assert( contains(u, "one"));
    assert(!contains(u, "two"));
#endif // 1
    std::map<std::string, int> m;
    m["one"] = 1;
    assert( contains(m, "one"));
    assert(!contains(m, "two"));

    std::vector<double> v;
    v.push_back(3.14);
    assert( contains(v, 3.14));
    assert(!contains(v, 0.00));
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]