Avoiding pointers in this C++ linked list
I see some things that may help you improve your code.

Write member initializers in declaration order

One of the constructors for node looks like this:

node(node * prev, node * next, const T &amp; data) :
        prev(prev), next(next), data(data) {
}


That looks fine, but in fact, next will be initialized before prev because members are always initialized in declaration order and next is declared before prev in this class. To avoid misleading another programmer, you should swap the order of those such that it says instead:

node(node * prev, node * next, const T &amp; data) :
        next(next), prev(prev), data(data) {
}


This way the initialization actually proceeds from left to right as one might expect at first glance.

Eliminate the default constructor

At the moment, one of the constructors for node is written like this:

node() : T() { }


However, this is not good at all since, if it were ever used, it would leave next and prev uninitialized.  Better would be to explicitly delete it like this:

node()  = delete;


Add a destructor

Because you're allocating memory with new you must also deallocate it with delete or your program will leak memory.  Here's one way to write it:

virtual ~linkedlist() {
    for (auto it = begin(); it != end(); it = begin()) {
        remove(it);
    }
}


Provide move semantics for iterators

Right now, it's not possible to do this:

linkedlist&lt;std::complex&lt;float&gt;&gt; ll;
ll.remove(ll.begin());


The reason is that ll.begin() is an "rvalue" and so can't be passed as a reference.  To fix this, create a version of remove with move semantics:

bool remove(iterator &amp;&amp;iterator) {
    if (iterator.current_node == &amp;first || iterator.current_node == &amp;last)
        return false;
    node *to_remove = iterator.current_node;
    to_remove-&gt;prev-&gt;next = to_remove-&gt;next;
    to_remove-&gt;next-&gt;prev = to_remove-&gt;prev;
    delete to_remove;
    return true;
}


Provide const versions of iterators

The cbegin() and cend() forms of the iterators are missing.  Here's a simple cbegin():

iterator cbegin() const {
    return iterator(first.next);
}


Provide an initializer_list constructor

At the moment, this form of the constructor doesn't work:

linkedlist&lt;std::complex&lt;float&gt;&gt; ll{{3,4}, {5,12}};


It's simple to add, however:

linkedlist(std::initializer_list&lt;T&gt; list) :
        first(nullptr, &amp;last, T()),
        last(&amp;first, &amp;last, T()) 
{
    for (auto &amp;item : list) {
        add(item);
    }
}


Provide copy function or delete it

At the moment, a copy function is compiler generated but almost certainly not what you want because it will only copy pointers and not the underlying data.  Either delete the function explicitly or provide one.

Provide member functions to suit the data structure

A linked list is not a very good data structure for many purposes, but one thing that is efficient is the ability to insert one linked list within another (a splice).  Unfortunately, this function is not provided, so any advantage is unrealized.

Provide a full iterator implementation

In order to use the algorithms in &lt;algorithm&gt;, you will need first class iterators, but although somewhat useful, yours are missing a number of pieces.  See this reference page for details on what a real iterator provides.