Skip to content

Commit a74f0bb

Browse files
committed
Merge pull request #10 from biddisco/master
Add a streamulus::reference wrapper for objects by reference
2 parents 1d0f609 + c24a63d commit a74f0bb

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/reference.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//
2+
// reference.h
3+
//
4+
// Streamulus Copyright (c) 2012 Irit Katriel. All rights reserved.
5+
//
6+
// This file is part of Streamulus.
7+
//
8+
// Streamulus is free software: you can redistribute it and/or modify
9+
// it under the terms of the GNU General Public License as published by
10+
// the Free Software Foundation, either version 3 of the License, or
11+
// (at your option) any later version.
12+
//
13+
// Streamulus is distributed in the hope that it will be useful,
14+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
// GNU General Public License for more details.
17+
//
18+
// You should have received a copy of the GNU General Public License
19+
// along with Streamulus. If not, see <http://www.gnu.org/licenses/>.
20+
//
21+
22+
#pragma once
23+
24+
#include <type_traits> // std::reference_wrapper
25+
26+
namespace streamulus
27+
{
28+
29+
// streamulus::reference
30+
// if you attempt to Streamify(FunctionObject) something that is noncopyable,
31+
// then compilation will fail since the copy constructor is used to move the function
32+
// object during expression transformation.
33+
//
34+
// To circumvent this, one may wrap the object to be streamified using this reference
35+
// streamulus::Streamify( streamulus::reference<Type>(instance) )(operand)
36+
//
37+
// This allows objects which are noncopyable, particularly those with
38+
// some internal state which might be used in other places to be streamified directly.
39+
// Note that this works only with the streamify variant which takes an instance of an object
40+
// and not the templated type version, for obvious reasons.
41+
42+
template <typename F>
43+
struct reference {
44+
// output type is same as wrapped object output type
45+
template <class Sig> struct result { typedef typename F::template result<F>::type type; };
46+
47+
// construct using a supplied object, initialize our reference wrapper
48+
inline reference<F>(F &internal) : mInternal(internal) {
49+
// std::cout << "streamulus_wrapper(F)" << std::endl;
50+
}
51+
52+
// copy constructor passes the reference to the new copy
53+
inline reference<F>(const reference<F> &other) : mInternal(other.mInternal) {
54+
// std::cout << "streamulus_wrapper(streamulus_wrapper(F))" << std::endl;
55+
};
56+
57+
// we must overload the () operator and call the wrapped object () operator
58+
// we'll use a templated parameter pack and let the compiler decide if the user
59+
// is doing it right, since we don't know what arguments the wrapped () operater takes
60+
template <typename... Args>
61+
inline typename F::template result<F>::type operator()(Args... args) {
62+
return mInternal.get().operator()(args...);
63+
}
64+
65+
private:
66+
const std::reference_wrapper<F> mInternal;
67+
};
68+
69+
} // ns streamulus

src/streamulus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "input_stream.h"
2626
#include "operators.h"
2727
#include "streamify.h"
28+
#include "reference.h"
2829
#include "strop_data_source.h"
2930

3031

0 commit comments

Comments
 (0)