Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 293471
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 12, 20262026-05-12T06:16:30+00:00 2026-05-12T06:16:30+00:00

I’m writing a templated C++ generic container class that can optionally maintain its contents

  • 0

I’m writing a templated C++ generic container class that can optionally maintain its contents in a well-defined order. Previously it used function pointers to order its contents in a sensible type-specific way, but I am attempting to change it to use templated functor arguments instead.

Since it’s often the case that the class’s user might want to keep items of the same type sorted in different ways in different containers, the container class takes an optional template argument that lets the user optionally specify his own compare-functor:

template <class ItemType, class CompareFunctorType = CompareFunctor<ItemType> > class MyContainer
{
    [...]
};

If the class user doesn’t specify a custom functor type, it uses the following CompareFunctor definition by default:

template <typename ItemType> class CompareFunctor
{
public:
    bool IsItemLessThan(const ItemType & a, const ItemType & b) const
    {
       return (a<b);   // will compile only for types with < operator
    }
};

This works great for built-in types and also user-defined types where a less-than operator has been defined. However, I’d like it to also automatically work for types where there is no built-in or explicitly defined less-than operator. For those types, the ordering of the items within the container is not important.

The motivation is that I use this container to hold a lot of different types, and most of the time, I don’t care about the order of the types in the container, but in some cases I do… and I don’t want to have to go in and add “dummy” less-than operators to all of these different types just so I can use them with this container class… and I don’t want to have to explicitly specify a custom “dummy” CompareFunctor argument every time I use the table to store items that don’t have a less-than operator.

So, is there a way I can use template specialization (or something) so that the default CompareFunctor (shown above) is used whenever possible, but in cases where that CompareFunctor would cause an error, C++ would automatically fall back to a “dummy” FallbackCompareFunctor like the one below? Or perhaps some other clever way to handle this dilemna?

template <typename ItemType> class FallbackCompareFunctor
{
public:
    bool IsItemLessThan(const ItemType & a, const ItemType & b) const
    {
       return ((&a)<(&b));   // will compile for all types (useful for types where the ordering is not important)
    }
};
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-12T06:16:30+00:00Added an answer on May 12, 2026 at 6:16 am

    In case anyone is interested, I was able to come up with a way to do what I wanted, using a combination of the techniques described above. My proof-of-concept code (with unit test) is shown below.

    #include <stdio.h>
    
    // Real functor, should be used by default when ItemType has a < operator
    template <typename ItemType> class RealCompareFunctor
    {
    public:
       bool IsLessThan(const ItemType & item1, const ItemType & item2)
       {
          printf(" --> RealCompareFunctor called!\n");
          return item1 < item2;
       }
    
       typedef ItemType TheItemType;
    };
    
    // Dummy functor, should be used by default when ItemType has no < operator
    template <typename ItemType> class DummyCompareFunctor
    {
    public:
       bool IsLessThan(const ItemType & item1, const ItemType & item2)
       {
          printf(" --> DummyCompareFunctor called!\n");
          return (&item1) < (&item2);
       }
    };
    
    namespace implementation_details
    {
        // A tag type returned by operator < for the any struct in this namespace when T does not support (operator <)
        struct tag {};
    
        // This type soaks up any implicit conversions and makes the following (operator <)
        // less preferred than any other such operator found via ADL.
        struct any
        {
            // Conversion constructor for any type.
            template <class T> any(T const&);
        };
    
        // Fallback (operator <) for types T that don't support (operator <)
        tag operator < (any const&, any const&);
    
        // Two overloads to distinguish whether T supports a certain operator expression.
        // The first overload returns a reference to a two-element character array and is chosen if
        // T does not support the expression, such as < whereas the second overload returns a char
        // directly and is chosen if T supports the expression. So using sizeof(check(<expression>))
        // returns 2 for the first overload and 1 for the second overload.
        typedef char yes;
        typedef char (&no)[2];
    
        no check(tag);
    
        template <class T> yes check(T const&);
    
        // Implementation for our has_less_than_operator template metafunction.
        template <class T> struct has_less_than_operator_impl
        {
            static const T & x;
            static const bool value = sizeof(check(x < x)) == sizeof(yes);
        };
    
       template <class T> struct has_less_than_operator : implementation_details::has_less_than_operator_impl<T> {};
    
       template <bool Condition, typename TrueResult, typename FalseResult>
       class if_;
    
       template <typename TrueResult, typename FalseResult>
       struct if_<true, TrueResult, FalseResult>
       {
         typedef TrueResult result;
       };
    
       template <typename TrueResult, typename FalseResult>
       struct if_<false, TrueResult, FalseResult>
       {
          typedef FalseResult result;
       };
    }
    
    template<typename ItemType> struct AutoChooseFunctorStruct
    {
       typedef struct implementation_details::if_<implementation_details::has_less_than_operator<ItemType>::value, RealCompareFunctor<ItemType>, DummyCompareFunctor<ItemType> >::result Type;
    };
    
    /** The default FunctorType to use with this class is chosen based on whether or not ItemType has a less-than operator */
    template <class ItemType, class FunctorType = struct AutoChooseFunctorStruct<ItemType>::Type > class Container
    {
    public:
       Container()
       {
          ItemType itemA;
          ItemType itemB;
          FunctorType functor;
          bool isLess = functor.IsLessThan(itemA, itemB);
          //printf(" --> functor says isLess=%i\n", isLess);
       }
    };
    
    // UNIT TEST CODE BELOW
    
    struct NonComparableStruct {};
    
    struct ComparableStructOne
    {
       bool operator < (ComparableStructOne const&) const { return true; }
    };
    
    struct ComparableStructTwo {};
    bool operator < (ComparableStructTwo const&, ComparableStructTwo const&) { return true; }
    
    class NonComparableClass
    {
    public:
       NonComparableClass() {/* empty */}
    };
    
    class ComparableClass
    {
    public:
       ComparableClass() {/* empty */}
    
       bool operator < (const ComparableClass & rhs) const {return (this < &rhs);}
    };
    
    int main(int argc, char * argv[])
    {
       printf("\nContainer<int>\n");
       Container<int> c1;
    
       printf("\nContainer<ComparableStructOne>\n");
       Container<ComparableStructOne> c2;
    
       printf("\nContainer<ComparableStructTwo>\n");
       Container<ComparableStructTwo> c3;
    
       printf("\nContainer<NonComparableStruct>\n");
       Container<NonComparableStruct> c4;
    
       printf("\nContainer<NonComparableClass>\n");
       Container<NonComparableClass> c5;
    
       printf("\nContainer<ComparableClass>\n");
       Container<ComparableClass> c6;
    
       return 0;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I have a bunch of posts stored in text files formatted in yaml/textile (from
We're building an app, our first using Rails 3, and we're having to build
I have this code: - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock { NSString *someString = [[NSString
I am trying to loop through a bunch of documents I have to put
I'm making a simple page using Google Maps API 3. My first. One marker
I have some data like this: 1 2 3 4 5 9 2 6

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.