title: Variant visitation and common_type
body: <p>I am wondering how <code>std::visit</code> return type conversions are supposed to work. </p>
  
  <p>The context is the following:
  I have a variant object and I want to apply (through <code>std::visit</code>) different functions depending on its underlying type. The result of each function may have a different type, but then I would like std::visit to pack it up in a variant type.</p>
  
  <p>Pseudo-code:</p>
  
  <p>I have:</p>
  
  <pre><code>variant&lt;A,B&gt; obj
  f(A) -&gt; A
  f(B) -&gt; B
  </code></pre>
  
  <p>I want:</p>
  
  <pre><code>if obj is of type A =&gt; apply f(A) =&gt; resA of type A =&gt; pack it in variant&lt;A,B&gt;
  if obj is of type B =&gt; apply f(B) =&gt; resB of type B =&gt; pack it in variant&lt;A,B&gt;
  </code></pre>
  
  <p>Now, according to <a href="http://en.cppreference.com/w/cpp/utility/variant/visit" rel="nofollow noreferrer">cppreference</a>, the return type of std::visit is "The value returned by the selected invocation of the visitor, converted to the common type of all possible std::invoke expressions"
  But what common type means is not specified. Is it <code>std::common_type</code> ? In this case, it doesn't work with gcc 7.2:</p>
  
  <pre><code>#include &lt;variant&gt;
  #include &lt;iostream&gt;
  #include &lt;type_traits&gt;
  
  struct A {
      int i;
  };
  struct B {
      int j;
  };
  
  // the standard allows to specialize std::common_type
  namespace std {
      template&lt;&gt;
      struct common_type&lt;A,B&gt; {
          using type = std::variant&lt;A,B&gt;;
      };
      template&lt;&gt;
      struct common_type&lt;B,A&gt; {
          using type = std::variant&lt;A,B&gt;;
      };
  }
  
  
  struct Functor {
      auto
      operator()(A a) -&gt; A {
          return {2*a.i};
      }
      auto
      operator()(B b) -&gt; B {
          return {3*b.j};
      }
  };
  
  
  int main() {
      std::variant&lt;A,B&gt; var = A{42};
  
      auto res = std::visit( Functor() , var ); // error: invalid conversion from 'std::__success_type&lt;B&gt;::type (*)(Functor&amp;&amp;, std::variant&lt;A, B&gt;&amp;) {aka B (*)(Functor&amp;&amp;, std::variant&lt;A, B&gt;&amp;)}' to 'A (*)(Functor&amp;&amp;, std::variant&lt;A, B&gt;&amp;)' [-fpermissive]
  
  }
  </code></pre>
  
  <p>What should I do to express this unpack - apply visitation - repack pattern?</p>
  
  <p><strong>Notes:</strong></p>
  
  <p>1) Specializing <code>std::common_type&lt;A(*)(Ts...),B(*)(Ts...)&gt;</code> won't cut it. This would do the trick but rely on a particular std::lib implementation detail.
      Plus it doesn't work for multi-visitation.</p>
  
  <p>2) The example I have given is really reduced to the bare minimum, but you have to imagine that the visitation mechanism I want to provide is on the library side, and the visitors are on the client side and can be arbitrary complicated: unknown number and types of arguments, unknown return types. The library should just provide visitation and a pre-defined set of <code>std::common_type</code> specializations to be used for visitation return types. So for instance, defining</p>
  
  <pre><code>auto f = [](auto x) -&gt; variant&lt;A,B&gt; { return Functor()(x); };
  </code></pre>
  
  <p>and then applying <code>std::visit</code> to <code>f</code> is not a viable option: from the library side, I can't predefine this kind of lambda without knowing the "packed" return type. [The main problem is that I see no way of asking the language for the <code>std::common_type</code> of a particular overload set]</p>