I don't think you can do this comfortably. You are trying to implement your own language on top of C++, but C++ doesn't really have this kind of extensibility.
The next best thing is a fluent interface. With a fluent interface, we can encode a grammar of our design into the type system. We can't enforce that only one special function per C++ block is called, but we can enforce that only one special method in our cascade is invoked. For example:
// Mixin for end() operation
struct can_end {
auto end() && -> void {}
};
// Mixin for normal methods
template<typename next_state>
struct can_normal {
auto normal_1() && -> next_state { return {}; }
auto normal_2() && -> next_state { return {}; }
};
// State after special method: only end and normal methods allowed
struct after_special : can_end, can_normal<after_special> {
after_special() = default;
after_special(after_special const&) = delete;
};
// State before special method: end, normal, and special allowed
struct before_special : can_end, can_normal<before_special> {
before_special() = default;
before_special(before_special const&) = delete;
auto special() && -> after_special { return {}; }
};
// Entry point
auto block() -> before_special { return {}; }
Now we can write a method cascade like:
block()
.normal_1()
.special()
.normal_2()
.end();
But will be prevented from invoking the special method twice:
block()
.special()
.special() // type error
.end();
By deleting the copy ctor, we prevent using a temporary variable to capture the pre-special state:
auto temp = block(); // compilation error: deleted copy ctor
temp.special();
temp.special().end();
As all methods take an rvalue reference, this also discourages trickery like binding the state to a reference and then invoking the special method twice. But I'm sure the C++ type system has enough escape hatches to do that if you're really determined.