Last active
December 12, 2015 00:59
-
-
Save kbenzie/4688057 to your computer and use it in GitHub Desktop.
Raw string literals, uniform initializers, initializer lists, move semantics, ranged for loops, variadic templates for perfect forwarding, auto, I think that's all the C++11 in there.
Also enable_if is_base_of in a class template.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Some C++11 features in use. | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
#include <type_traits> | |
using namespace std; | |
// Raw string literal | |
string vertex_shader_source = R"glsl(#version 330 | |
layout (location = 0) in vec3 vertex_position; | |
out vec3 position; | |
void main() | |
{ | |
position = vertex_position; | |
gl_Position = vec4(vertex_position, 1); | |
})glsl"; | |
// Simple base class | |
class widget_base { | |
public: | |
widget_base() {} | |
virtual ~widget_base() {} | |
virtual void print() = 0; | |
private: | |
// Disallow copying | |
widget_base(const widget_base &); | |
widget_base & operator=(const widget_base &); | |
}; | |
// Simple derived widget class with copy & move constructors | |
class simple_widget : public widget_base { | |
public: | |
// Constructor accepting rvalues references, can move temporary objects | |
simple_widget(std::vector<int> &&integers) | |
: integers{move(integers)} | |
{} | |
// Copy constructor | |
simple_widget(const simple_widget &w) | |
: widget_base() | |
, integers(w.integers) | |
{} | |
// Move constructor | |
simple_widget(simple_widget &&w) | |
: widget_base() | |
, integers(move(w.integers)) | |
{ | |
// Member pointers would be copied: ptr = w.ptr; | |
// then set: w.ptr = nullptr; | |
} | |
virtual void print() { | |
for (auto i : integers) { | |
cout << i << " "; | |
} | |
cout << "\n"; | |
} | |
private: | |
std::vector<int> integers; | |
}; | |
// Derived widget class with multiple constructor arguments | |
class multi_widget : public widget_base { | |
public: | |
// Constructor accepting rvalues references, can move temporary objects | |
multi_widget(std::string &&name, std::vector<int> &&integers) | |
: name(move(name)) | |
, integers{move(integers)} | |
{} | |
void print() { | |
string out; | |
out += name + " has\n"; | |
// Ranged for loop | |
for (auto i : integers) { | |
// Basic type to_string() function | |
out += to_string(i) + " "; | |
} | |
cout << out + "\n"; | |
} | |
private: | |
string name; | |
vector<int> integers; | |
}; | |
// Not a widget | |
class not_a_widget { | |
public: | |
// Same internals as simple_widget | |
not_a_widget(std::vector<int> &&integers) | |
: integers{move(integers)} | |
{} | |
virtual void print() { | |
// Ranged for loop | |
for (auto i : integers) { | |
cout << i << " "; | |
} | |
cout << "\n"; | |
} | |
private: | |
std::vector<int> integers; | |
}; | |
// Generic container class | |
template <class Widget, typename = typename enable_if<is_base_of<widget_base, Widget>::value>::type> | |
class container { | |
public: | |
// Perfect forwarding using variadic template (...) | |
template <typename... Args> | |
container(Args&&... args) | |
: widget{move(args)...} | |
{} | |
void print() { | |
widget.print(); | |
} | |
private: | |
Widget widget; | |
}; | |
int main() | |
{ | |
// Raw string literals make writing shaders into a string very easy. | |
cout << vertex_shader_source << "\n"; | |
// Using the move function maintains the && when passing an temporary | |
// object as a function argument, otherwise reference folding would turn | |
// it into a & resulting in no move. | |
container<simple_widget> simple{move(vector<int>{1,2,3,4,5,6,7,8,9})}; | |
// | ^Initializer list ^ | | |
// ^ Uniform initialisation ^ | |
cout << "simple_widget has:\n"; | |
simple.print(); | |
container<multi_widget> multi{move(string("multi_widget")), move(vector<int>{1,2})}; | |
// | Initializer list ^^^^^ | | |
// ^ Uniform initialisation ^ | |
multi.print(); | |
// Won't compile, disabled by enable_if beacuse not_a_widget is not derived | |
// from widget_base. | |
// container<not_a_widget> not_a(move(vector<int>{1,2,3,4,5})); | |
// // Initializer list ^^^^^^^^^^^ | |
// not_a.print(); | |
simple_widget original{move(vector<int>{1,2,3})}; | |
// ^ Uniform initialisation ^ is a unified syntax for | |
// initialisation of objects, array etc. across the language. | |
auto copied = original; | |
cout << "origial has been copied\n"; | |
cout << "original: "; | |
original.print(); | |
cout << "copied: "; | |
copied.print(); | |
auto moved = move(original); | |
cout << "origial has been moved\n"; | |
cout << "original: "; | |
original.print(); | |
cout << "copied: "; | |
copied.print(); | |
cout << "moved: "; | |
moved.print(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment