Simple c++ triple class to mimic pair for use with uniform initialization
While the code you have appears to work as you expect, your stated reason for using it doesn't make sense to me, because one could use std::tuple with uniform initialization as well.

Use std::tuple

With only a relatively minor change to your print routine, the main you have could be used just as easily with std::tuple:

void print(const std::vector&lt;std::tuple&lt;int, const std::string, const std::string&gt;&gt; &amp;vals) {
   for(auto &amp;tup : vals) {
        std::cout &lt;&lt; "First:  " &lt;&lt; std::get&lt;0&gt;(tup) &lt;&lt; std::endl
                  &lt;&lt; "Second: " &lt;&lt; std::get&lt;1&gt;(tup) &lt;&lt; std::endl
                  &lt;&lt; "Third:  " &lt;&lt; std::get&lt;2&gt;(tup) &lt;&lt; std::endl;
        std::cout &lt;&lt; "------------------" &lt;&lt; std::endl;
   }
}


Answer 1

The reason those typedefs are there is that they're required by the standard.  That way, it's easy to be able to create other variables of the same type as, say, the second argument, without having to jump through a lot of hoops.  In other words, it's a convenience for the user of the template rather than for the author of the template.  

Answer 2

I wouldn't bother with static asserts.  If you did want to restrict the kinds of things that can be stored, it's probably better to use std::enable_if.  

Answer 3

I'm not sure, but I suspect that the other types U1 and U2 are required for convertable but non-identical classes that might be used to construct the triple (as you've surmised).

Answer 4

Only one alarm -- why aren't you using std::tuple?  :)

Try it live.