Q: What is the best way to declare multiple argument constructor in C++11 When creating a class like this one:
class Test {
 public:
   ...

private:
   string s1_;
   string s2_;
   vector<int> v_;
};

What is the best way to declare a constructor accepting two strings and a vector? And, more specifically, how do you handle lvalue and rvalue references?
I see the three following options:


*

*Create every combination of lvref and rvref:
   Test(const string& s1, const string& s2, const vector<int>& v) :
      s1_{s1}, s2_{s2}, v_{v}
   {
      ...
   }

   Test(const string& s1, const string& s2, vector<int>&& v) :
      s1_{s1}, s2_{s2}, v_{move(v)}
   {
      ...
   }

   Test(const string& s1, string&& s2, const vector<int>& v) :
      s1_{s1}, s2_{move(s2)}, v_{v}
   {
      ...
   }

   Test(const string& s1, string&& s2, vector<int>&& v) :
      s1_{s1}, s2_{move(s2)}, v_{move(v)}
   {
      ...
   }

   Test(string&& s1, const string& s2, const vector<int>& v) :
      s1_{move(s1)}, s2_{s2}, v_{v}
   {
      ...
   }

   Test(string&& s1, const string& s2, vector<int>&& v) :
      s1_{move(s1)}, s2_{s2}, v_{move(v)}
   {
      ...
   }

   Test(string&& s1, string&& s2, const vector<int>& v) :
      s1_{move(s1)}, s2_{move(s2)}, v_{v}
   {
      ...
   }

   Test(string&& s1, string&& s2, vector<int>&& v) :
      s1_{move(s1)}, s2_{move(s2)}, v_{move(v)}
   {
      ...
   }

Pros: Every possibility handled efficiently.
Cons: Requires a lot of code to handle every combination and might be error prone.

*Always copy and move the arguments:
   Test(string s1, string s2, vector<int> v) :
      s1_{move(s1)}, s2_{move(s2)}, v_{move(v)}
   {
      ...
   }

Pros: Only one ctor.
Cons: Not as efficient because move does not mean free.

*Use "universal references":
   template <typename S1, typename S2, typename V>
   Test(S1&& s1, S2&& s2, V&& v) :
      s1_{forward<S1>(s1)}, s2_{forward<S2>(s2)}, v_{forward<V>(v)}
   {
      ...
   }

Pros: One ctor that handles everything efficiently.
Cons: Not really meaningful. What are s1, s2 and v? Can be even more error prone (e.g. Test error{1,2,3} compiles).
Is there a better way to achieve that?

A: What about:
template <typename String, typename VectorInt>
Test(String &&s1, String &&s2, VectorInt &&v,
  typename std::enable_if<std::is_same<typename std::decay<String>::type,std::string>::value &&
  std::is_same<typename std::decay<VectorInt>::type,std::vector<int>>::value>::type * = nullptr) :
  s1_(std::forward<String>(s1)), s2_(std::forward<String>(s2)),
  v_(std::forward<VectorInt>(v))
{}

