1

How would I go about making a function that uses braces like if/for/while statements? I'm referring to this as a 'keyword statement' because I don't know what else to call it.

Meaning, for example, if I wanted to make a 'repeat' function:

repeat(3)
{
    //do something
}

I guess a better question is, is this possible? If so, how would one go about doing this?

Gurman8r
  • 301
  • 1
  • 4
  • 19

3 Answers3

8

Don't do that [#define repeat] - don't try to change the syntax of the programming language you're using. That will make your code far less readable for anyone else.

Vincent Fourmond
  • 3,038
  • 1
  • 22
  • 24
  • I'm purely curious on this one. Just wondering if/how it was possible. – Gurman8r Oct 13 '15 at 19:35
  • 1
    @Gurman8r It is possible using macros, but as said elsewhere, "macros are evil" http://stackoverflow.com/questions/14041453/why-are-preprocessor-macros-evil-and-what-are-the-alternatives – Vincent Fourmond Oct 13 '15 at 19:39
7

You might define a range similar to a python range:

// Range
// =====

#include <iterator>
#include <utility>

template<typename T>
class Range
{
    public:
    typedef T value_type;

    public:
    class iterator
    {
        public:
        typedef typename std::forward_iterator_tag iterator_category;
        typedef typename std::size_t size_type;
        typedef typename std::ptrdiff_t difference_type;
        typedef T value_type;
        typedef const T& reference;
        typedef const T* pointer;

        public:
        iterator(const T& value) noexcept
        :   m_value(value)
        {}

        reference operator * () const noexcept { return m_value; }
        pointer operator -> () const noexcept { return &m_value; }
        iterator& operator ++ () noexcept { ++m_value; return *this; }

        friend bool operator == (const iterator & a, const iterator b) noexcept {
            return a.m_value == b.m_value;
        }
        friend bool operator != (const iterator & a, const iterator b) noexcept {
            return a.m_value != b.m_value;
        }

        private:
        T m_value;
    };

    public:
    Range(const T& first, const T& last) noexcept
    :   m_first(first), m_last(last)
    {}

    Range(T&& first, T&& last) noexcept
    :   m_first(std::move(first)), m_last(std::move(last))
    {}

    Range(Range&& other) noexcept
    :   m_first(std::move(other.m_first)),
        m_last(std::move(other.m_last))
    {}

    Range& operator = (Range&& other) noexcept {
        m_first = std::move(other.m_first);
        m_last = std::move(other.m_last);
        return *this;
    }

    iterator begin() const noexcept { return  m_first; }
    iterator end() const noexcept { return m_last; }

    private:
    T m_first;
    T m_last;
};

template<typename T>
inline Range<T> range(T&& first, T&& last) noexcept {
    return Range<T>(std::move(first), std::move(last));
}


// Test
// ====

#include <iostream>

int main() {
    for(auto i : range(0, 3))
        std::cout << i << '\n';
}

A more sophisticated implementation would consider containers and iterators, too.

5

You could define a macro taking 1 argument:

#define repeat(COUNT) \
    for (unsigned int i = 0; i < (COUNT); ++i)

and leave the brakets empty after it, the preprocessor will expand the following example:

repeat(3)
{
    //do something
}

into:

for (unsigned int i = 0; i < (3); ++i)
{
    //do something
}

Demo

Naios
  • 1,513
  • 1
  • 12
  • 26
  • Cool, thanks. I'll mark your answer when it let's me. – Gurman8r Oct 13 '15 at 19:33
  • 4
    What if I write `repeat(++n)`? No, seriously, I like the answer and upvoted it, but someone could actually try that and get in trouble. – void_ptr Oct 13 '15 at 19:33
  • 2
    @Gurman8rrPleeeeeease, don't follow such silly advice. It will just bite you in the ass, sooner as you can say _meow_! – πάντα ῥεῖ Oct 13 '15 at 19:35
  • 1
    The argument doesn't have to be `++n` to get you into trouble. What if it were simply an expensive (though reproducible) computation? Better (but still ugly and unnecessary) would be `#define repeat(count) for (auto n_ = count; n_; --n_)` – rici Oct 13 '15 at 19:58
  • This is really cool, but as a novelty. I would hate to see code like this, but this +1 for showing how its done. – AustinWBryan Dec 18 '22 at 06:11