Skip to content

Instantly share code, notes, and snippets.

@kbenzie
Last active December 12, 2015 00:59
Show Gist options
  • Save kbenzie/4688057 to your computer and use it in GitHub Desktop.
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.
// 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