Skip to content

Instantly share code, notes, and snippets.

@sjolsen
Created September 24, 2014 23:47
Show Gist options
  • Save sjolsen/33c2b031b25375e16a47 to your computer and use it in GitHub Desktop.
Save sjolsen/33c2b031b25375e16a47 to your computer and use it in GitHub Desktop.
Dynamic scope in C++
#include <utility>
#include <cassert>
template <typename T>
class dynamic_binding;
template <typename T>
class dynamic_variable
{
T _initial_object;
T* _current_binding = &_initial_object;
protected:
friend class dynamic_binding <T>;
T* _rebind (T* new_binding)
{
T* old_binding = _current_binding;
_current_binding = new_binding;
return old_binding;
}
public:
using value_type = T;
template <typename... Args>
dynamic_variable (Args&&... args)
: _initial_object (std::forward <Args> (args)...)
{
}
operator T& ()
{
return *_current_binding;
}
};
template <typename T>
class dynamic_binding
{
T _local_object;
T* _previous_binding;
dynamic_variable <T>& _variable;
public:
template <typename... Args>
dynamic_binding (dynamic_variable <T>& variable, Args&&... args)
: _local_object (std::forward <Args> (args)...),
_variable (variable)
{
_previous_binding = _variable._rebind (&_local_object);
}
~dynamic_binding ()
{
assert (_variable._rebind (_previous_binding) == &_local_object);
}
};
#define CATENATE_IMPL(FOO, BAR) FOO##BAR
#define CATENATE(FOO, BAR) CATENATE_IMPL (FOO, BAR)
#define GENSYM(S) CATENATE (S##_, __COUNTER__)
#define DYNAMIC_BIND(NAME, ...) dynamic_binding <typename decltype (NAME)::value_type> GENSYM (local_binding) (NAME, ##__VA_ARGS__)
#include <iostream>
thread_local
dynamic_variable <std::ostream*> my_output = &std::cout;
void print ()
{
}
template <typename First, typename... Rest>
void print (First&& first, Rest&&... rest)
{
*my_output << std::forward <First> (first);
print (std::forward <Rest> (rest)...);
}
int main ()
{
print ("Hello, ", "World!", '\n');
{
DYNAMIC_BIND (my_output, &std::cerr);
print ("Hello, stderr!\n");
}
print ("Standard output, is that you?\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment