Skip to content

Instantly share code, notes, and snippets.

@mmocny
Last active December 26, 2015 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmocny/7204756 to your computer and use it in GitHub Desktop.
Save mmocny/7204756 to your computer and use it in GitHub Desktop.
Motivated by http://ericniebler.com/2013/10/13/out-parameters-vs-move-semantics/ I'm playing with a possible simple solution to the problem of solving optionally useful InOut variables in C++11 given that the interface is ugly, but occasionally really necessary. Below is a seemingly working solution, which I truly suspected of being undefined be…
#include <iostream>
#include <string>
#include <algorithm>
/*
* Sample Output: http://ideone.com/EbKsF5
*
* Tested on: g++ 4.7, g++ 4.8, clang 3.3
*
*/
// Use this class to wrap std::string, just to inject printing of calls to copy/move etc
struct StringWrapper : std::string {
// Any Constructor, including copy&move
template<class... T>
StringWrapper(T&&... t) : std::string(std::forward<T>(t)...) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
// Any Assignment, including copy&move
template<class T>
StringWrapper& operator=(T&& other) {
std::string::operator=(std::forward<T>(other));
std::cout << __PRETTY_FUNCTION__ << std::endl;
return *this;
}
~StringWrapper() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
// Utilities: dup, sorted, filtered
// *************************************
// **** This is the interesting bit ****
// *************************************
//
// The following duplicates a containers' content.
//
// It takes an option 2nd input-output argument as a hint. Input-Output in this case means that
// the result is written to it (output), but its original state (capacity) is used as "input".
//
template <class In, class InOut = StringWrapper>
InOut&& dup(In const& in, InOut&& inout = InOut{}) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << "cap: " << inout.capacity() << ", sz: " << inout.size() << std::endl;
inout.assign(std::begin(in), std::end(in));
inout.append(std::begin(in), std::end(in));
std::cout << "cap: " << inout.capacity() << ", sz: " << inout.size() << std::endl;
return std::forward<InOut>(inout);
}
//
// *************************************
// *************************************
template<class C>
C sorted(C c) {
std::sort(std::begin(c), std::end(c));
return c;
}
template<class C, class T>
C filtered(C c, T&& t) {
c.erase(std::remove(std::begin(c), std::end(c), std::forward<T>(t)), std::end(c));
return c;
}
// Now, lets test all the common possible use cases.
int main() {
std::string kInput = "long test string, >default string cap.";
{
std::cout << "[Test] Good ol' fashioned Explicit-In-Out" << std::endl;
StringWrapper s;
s.reserve(100);
dup(kInput, s);
std::cout << s << std::endl;
}
{
std::cout << "[Test] Temporary" << std::endl;
std::cout << dup(kInput) << std::endl;
}
{
std::cout << "[Test] Temporary-with-Piped-Actions" << std::endl;
std::cout << filtered(sorted(dup(kInput)), 't') << std::endl;
}
{
std::cout << "[Test] Temporary-with-Hint" << std::endl;
std::cout << dup(kInput, StringWrapper(100, ' ')) << std::endl;
}
{
std::cout << "[Test] Move-Init-from-Temporary" << std::endl;
StringWrapper s = dup(kInput);
std::cout << s << std::endl;
}
{
std::cout << "[Test] Move-Init-from-Temporary-with-Temporary-Hint" << std::endl;
StringWrapper s = dup(kInput, StringWrapper(100, ' '));
std::cout << s << std::endl;
}
{
std::cout << "[Test] Move-Assign-from-Temporary" << std::endl;
StringWrapper s;
s = dup(kInput);
std::cout << s << std::endl;
}
{
std::cout << "[Test] Move-Assign-from-Temporary-with-Hint-of-Self" << std::endl;
StringWrapper s(100, ' ');
s = dup(kInput, s);
std::cout << s << std::endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment