diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index 8fa41a3b314ff59294b6d9c991f799a77fe6e6e1..c20484621e0f5947fb9e18128096fc03e80180ea 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -16,7 +16,7 @@ from .Code import UtilityCode, LazyUtilityCode, TempitaUtilityCode
 from . import StringEncoding
 from . import Naming
 
-from .Errors import error
+from .Errors import error, warning
 
 
 class BaseType(object):
@@ -3555,12 +3555,20 @@ class CppClassType(CType):
             error(pos, "'%s' type is not a template" % self)
             return error_type
         if len(self.templates) - self.num_optional_templates <= len(template_values) < len(self.templates):
+            num_defaults = len(self.templates) - len(template_values)
             partial_specialization = self.declaration_code('', template_params=template_values)
+            # Most of the time we don't need to declare anything typed to these
+            # default template arguments, but when we do there's no way in C++
+            # to reference this directly.  However, it is common convention to
+            # provide a typedef in the template class that resolves to each
+            # template type.  For now, allow the user to specify this name as
+            # the template parameter.
+            # TODO: Allow typedefs in cpp classes and search for it in this
+            # classes scope as a concrete name we could use.
             template_values = template_values + [
-                TemplatePlaceholderType("%s %s::%s" % (
-                    TemplatePlaceholderType.UNDECLARABLE_DEFAULT, partial_specialization, param.name),
-                    True)
-                for param in self.templates[-self.num_optional_templates:]]
+                TemplatePlaceholderType(
+                    "%s::%s" % (partial_specialization, param.name), True)
+                for param in self.templates[-num_defaults:]]
         if len(self.templates) != len(template_values):
             error(pos, "%s templated type receives %d arguments, got %d" %
                   (self.name, len(self.templates), len(template_values)))
@@ -3684,17 +3692,12 @@ class CppClassType(CType):
 
 class TemplatePlaceholderType(CType):
 
-    UNDECLARABLE_DEFAULT = "undeclarable default "
-
     def __init__(self, name, optional=False):
         self.name = name
         self.optional = optional
 
     def declaration_code(self, entity_code,
             for_display = 0, dll_linkage = None, pyrex = 0):
-        if self.name.startswith(self.UNDECLARABLE_DEFAULT) and not for_display:
-            error(None, "Can't declare variable of type '%s'"
-                % self.name[len(self.UNDECLARABLE_DEFAULT) + 1:])
         if entity_code:
             return self.name + " " + entity_code
         else:
diff --git a/docs/src/userguide/wrapping_CPlusPlus.rst b/docs/src/userguide/wrapping_CPlusPlus.rst
index bec84c761e0fafeca57381e4201b5159936af7b3..92791f3454db321f4e2e18a4efa71ca4484fb19b 100644
--- a/docs/src/userguide/wrapping_CPlusPlus.rst
+++ b/docs/src/userguide/wrapping_CPlusPlus.rst
@@ -68,7 +68,7 @@ document. Let's assume it will be in a header file called
             void move(int dx, int dy);
         };
     }
-    
+
 and the implementation in the file called :file:`Rectangle.cpp`:
 
 .. sourcecode:: c++
@@ -104,7 +104,7 @@ and the implementation in the file called :file:`Rectangle.cpp`:
             x1 += dx;
             y1 += dy;
         }
-  
+
     }
 
 This is pretty dumb, but should suffice to demonstrate the steps involved.
@@ -196,7 +196,7 @@ class name from Rectangle.h and adjust for Cython syntax, so now it becomes::
 
     cdef extern from "Rectangle.h" namespace "shapes":
         cdef cppclass Rectangle:
-    
+
 Add public attributes
 ^^^^^^^^^^^^^^^^^^^^^^
 
@@ -346,9 +346,9 @@ nested in Cython::
             T& at(int)
             iterator begin()
             iterator end()
-            
+
     cdef vector[int].iterator iter  #iter is declared as being of type vector<int>::iterator
-            
+
 Note that the nested class is declared with a ``cppclass`` but without a ``cdef``.
 
 C++ operators not compatible with Python syntax
@@ -409,8 +409,15 @@ Cython uses a bracket syntax for templating. A simple example for wrapping C++ v
 
     del v
 
-Multiple template parameters can be defined as a list, such as [T, U, V]
-or [int, bool, char].  Template functions are defined similarly, with
+Multiple template parameters can be defined as a list, such as ``[T, U, V]``
+or ``[int, bool, char]``.  Optional template parameters can be indicated
+by writing ``[T, U, V=*]``.  In the event that Cython needs to explicitly
+reference a default template value for an incomplete template instantiation,
+it will write ``MyClass<T, U>::V``, so if the class provides a typedef
+for its template parameters it is preferable to use that name here.
+
+
+Template functions are defined similarly to class templates, with
 the template parameter list following the function name::
 
     cdef extern from "<algorithm>" namespace "std":
@@ -437,7 +444,7 @@ For example::
         vect.push_back(i)
     for i in range(10):
         print vect[i]
-        
+
 The pxd files in ``/Cython/Includes/libcpp`` also work as good examples on
 how to declare C++ classes.
 
@@ -601,7 +608,7 @@ module which:
 
 * includes the needed C headers in an extern "C" block
 * contains minimal forwarding functions in C++, each of which calls the
-  respective pure-C function 
+  respective pure-C function
 
 Declaring/Using References
 ---------------------------
@@ -614,5 +621,3 @@ C++ left-values
 C++ allows functions returning a reference to be left-values.  This is currently
 not supported in Cython. ``cython.operator.dereference(foo)`` is also not
 considered a left-value.
-
-
diff --git a/tests/run/cpp_templates.pyx b/tests/run/cpp_templates.pyx
index b68f2f5218a77751a25786c84c5024510de83e18..88365c86142b1ce13a7d6c82b9c597d3917c9f7d 100644
--- a/tests/run/cpp_templates.pyx
+++ b/tests/run/cpp_templates.pyx
@@ -3,14 +3,17 @@
 from cython.operator import dereference as deref
 
 cdef extern from "cpp_templates_helper.h":
-    cdef cppclass Wrap[T, S=*]:
+    cdef cppclass Wrap[T, AltType=*, UndeclarableAltType=*]:
         Wrap(T)
         void set(T)
         T get()
         bint operator==(Wrap[T])
 
-        S get_alt_type()
-        void set_alt_type(S)
+        AltType get_alt_type()
+        void set_alt_type(AltType)
+
+        UndeclarableAltType create()
+        bint accept(UndeclarableAltType)
 
     cdef cppclass Pair[T1,T2]:
         Pair(T1,T2)
@@ -68,15 +71,17 @@ def test_default_template_arguments(double x):
     """
     try:
         a = new Wrap[double](x)
-        b = new Wrap[double, int](x)
+        b = new Wrap[double, int, long](x)
+
+        ax = a.get_alt_type()
+        a.set_alt_type(ax)
+        assert a.accept(a.create())  # never declared
 
-#        ax = a.get_alt_type()
-#        a.set_alt_type(ax)
-        a.set_alt_type(a.get_alt_type())
+        bx = b.get_alt_type()
+        b.set_alt_type(bx)
 
-#        bx = b.get_alt_type()
-#        b.set_alt_type(bx)
-        b.set_alt_type(b.get_alt_type())
+        bc = b.create()              # declaration here is fine
+        assert b.accept(bc)
 
         return a.get(), b.get()
     finally:
diff --git a/tests/run/cpp_templates_helper.h b/tests/run/cpp_templates_helper.h
index a685db6afcf36a53f776b25826cbc01e81e1f670..8973e6c5bf618d00af4428ae5ec9c2df61801083 100644
--- a/tests/run/cpp_templates_helper.h
+++ b/tests/run/cpp_templates_helper.h
@@ -1,7 +1,9 @@
-template <typename T, typename S=T>
+template <typename T, typename S=T, typename U=T>
 class Wrap {
     T value;
 public:
+    typedef S AltType;
+
     Wrap(T v) : value(v) { }
     void set(T v) { value = v; }
     T get(void) { return value; }
@@ -9,6 +11,9 @@ public:
 
     S get_alt_type(void) { return (S) value; }
     void set_alt_type(S v) { value = (T) v; }
+
+    U create(void) { return (U) value; }
+    bool accept(U v) { return v == (U) value; }
 };
 
 template <class T1, class T2>