STL Stack Implementation
I would appreciate all criticism relevant to code, style, flow, camelCase vs underscore, and so forth. 


First, (contrary to Loki Astari's answer) I think your style is correct (i.e. please do not capitalize the first letter of your classes - keep them matching the std:: style).

Regarding the APIs of your code:


Your code doesn't enforce const correctness
For argument types, consider the following convention:


Observed parameter (no modification of the value in the function)

void function(const argument&amp; a);

I/O parameter (function modifies the parameter, not owner):

void function(argument&amp; a); // a is modified in the function (I/O parameter)

Owned parameter:

void function(argument a); // function "owns" a (gets it's own exclusive copy)




Following this, push() and top() should be written like this:

template&lt;typename T&gt;
void stack&lt;T&gt;::push(T data) // pass by value here
{
    root = new node{ std::move(data), root }; // and move the value here
    ++elements;
}

template&lt;typename T&gt;
const T&amp;                // return a const T&amp;
stack&lt;T&gt;::top() const   // and function is const               
{
    if (!root)
        throw std::runtime_error("stack&lt;T&gt;::top: empty stack");
    return root-&gt;data;
}


Taking a parameter by value in push has these advantages:


specifies ownership in the interface
enables you to use all constructors of type T here
is exception safe (if the instance of the arg cannot be created, code will fail before entering the function body).
The size API:

int size();


Should be:

std::size_t size() const;



The print API has more problems:


It clears the list (either rename to "destructive_print", or ensure the iteration is not destructive). If you implement it in a non-destructive way, mark it const.
It introduces a dependency on std::cout that has nothing to do with the functionality of objects. Ideally, it shouldn't be a member. If you still want to have it as a member, pass the output stream instance as a parameter.


The constructor of the node class should construct a fully valid instance in one step. To decide on it's parameters, you should look at how you use it:

Usage example (your old code):

root_node = new node;
root_node-&gt;node_data = data;
root_node-&gt;next = nullptr;


Optimal example (new client code):

root_node = new node{ std::move(data), root_node }; // use std::move on the data


implies the node should be implemented like this:

template &lt;class T&gt;
class stack {
    // ...
    struct node { // struct, because it is internal and only
                  // access will be in stack
                  // (i.e. we can guarantee correct use in client code)

         T *node_data;
         node* next;
    };
}


The size should also be of std::size_t type.

Your stack doesn't have a destructor. The destructor should call delete on each node, in an iteration).

Your print element skips the last element in the list, as you begin indexing from 1 instead of 0, to less than number of elements. This means you iterate [elements - 1] times.

The pop() implementation can be written with no special case for one element:

template &lt;class T&gt;
void stack&lt;T&gt;::pop() {
    if(empty())
        throw std::runtime_error{"stack&lt;T&gt;::pop(): empty stack"};

    node* new_root = root_node-&gt;next;
    delete root_node;
    root_node = new_root;
    --elements;
}


Regarding the implementation of your class:

Do not print error messages, throw exceptions (this allows client code to decide what to do in case of an error, instead of forcing client code to get messages printed into it's application's output stream).