Compile-time range check?

Discussion in 'C++' started by Daniel Pitts, May 27, 2008.

  1. Daniel Pitts

    Daniel Pitts Guest

    I have a template:

    template<typename c, unsigned size>
    struct Vector {
    c components[size];
    template<unsigned index>
    c &get() { return components[index]; }
    };

    Vector<double, 3> vect;
    Is there a way to cause vect.get<3>() to fail at compile time. but
    vect.get<2>() have compile successfully?


    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, May 27, 2008
    #1
    1. Advertising

  2. Daniel Pitts

    Daniel Pitts Guest

    Victor Bazarov wrote:
    > Daniel Pitts wrote:
    >> I have a template:
    >>
    >> template<typename c, unsigned size>
    >> struct Vector {
    >> c components[size];
    >> template<unsigned index>
    >> c &get() { return components[index]; }
    >> };
    >>
    >> Vector<double, 3> vect;
    >> Is there a way to cause vect.get<3>() to fail at compile time. but
    >> vect.get<2>() have compile successfully?

    >
    > Sure. Read up on compile-time asserts.
    >
    > Here is what I could come up with (in five minutes or so it took to type
    > it up):
    >
    > template<unsigned low, unsigned test, unsigned high>
    > struct is_seq {
    > static char _[low <= test && test <= high];
    > static const bool yes = sizeof(_);
    > };
    > ...
    > template<unsigned index> c &get() {
    > return is_seq<0,index,size-1>::yes, components[index];
    > }
    >
    > V

    Thanks.
    I can be more specific than that, because all I really care about is
    0..max. I managed to come up with:

    template<bool>
    struct InvalidIndex{};

    template<>
    struct InvalidIndex<false>{ enum { isValid }; };

    template<unsigned index, unsigned max>
    struct ValidIndex {
    enum { isValid = InvalidIndex<index >= max>::isValid };
    };

    Thanks for the reply.

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, May 27, 2008
    #2
    1. Advertising

  3. Daniel Pitts

    Fei Liu Guest

    Daniel Pitts wrote:
    > I have a template:
    >
    > template<typename c, unsigned size>
    > struct Vector {
    > c components[size];
    > template<unsigned index>
    > c &get() { return components[index]; }
    > };
    >
    > Vector<double, 3> vect;
    > Is there a way to cause vect.get<3>() to fail at compile time. but
    > vect.get<2>() have compile successfully?
    >
    >

    please check BOOST_STATIC_ASSERT.
    Fei Liu, May 27, 2008
    #3
  4. Daniel Pitts

    Noah Roberts Guest

    Daniel Pitts wrote:
    > I have a template:
    >
    > template<typename c, unsigned size>
    > struct Vector {
    > c components[size];
    > template<unsigned index>
    > c &get() { return components[index]; }
    > };
    >
    > Vector<double, 3> vect;
    > Is there a way to cause vect.get<3>() to fail at compile time. but
    > vect.get<2>() have compile successfully?
    >
    >

    Another alternative is to use boost::enable_if and mpl helpers.

    #include <iostream>

    #include <boost/mpl/and.hpp>
    #include <boost/mpl/int.hpp>
    #include <boost/utility/enable_if.hpp>
    #include <boost/mpl/greater.hpp>
    #include <boost/mpl/less.hpp>

    namespace mpl = boost::mpl;

    template < typename C, unsigned SIZE >
    struct Vector
    {
    C components[SIZE];

    template < unsigned I >
    typename boost::enable_if
    <
    mpl::and_
    <
    mpl::greater< mpl::int_<I>, mpl::int_<-1> >
    , mpl::less< mpl::int_<I>, mpl::int_<SIZE> >
    >

    , C &
    >::type get()

    {
    return components;
    }
    };

    int main()
    {
    Vector<double, 3> v = { 42.3, 66.6, 0.1 };

    std::cout << v.get<1>() << std::endl;
    //std::cout << v.get<3>() << std::endl;

    std::cin.get();
    }

    Of course, you'll probably wish to clean that up a bit by writing your
    own range checking metafunction.
    Noah Roberts, May 27, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    46
    Views:
    949
    Antoon Pardon
    Jul 25, 2006
  2. flamesrock
    Replies:
    8
    Views:
    438
    Hendrik van Rooyen
    Nov 24, 2006
  3. Nagaraj
    Replies:
    1
    Views:
    841
    Lionel B
    Mar 1, 2007
  4. Carter
    Replies:
    2
    Views:
    490
    Carter
    Mar 4, 2009
  5. loudking
    Replies:
    3
    Views:
    469
    Ben Bacarisse
    Nov 30, 2009
Loading...

Share This Page