Returning anonymous struct from template function (for structured binding)

I wanted to use new C++17 features and wanted to use a structured binding to return multiple values from a (template) function. I can get it to work, but I want it to work better. A simplified version of the code is (the real code is larger and have better variable names):

template <class O>
struct {
  int a;
  double b;
} F(int i,O o) {
   return {i, o(i)};
}
void foo(int i) {
   auto [a,b]=F(i, [=](int k)->double {return 1.0/k; /*...*/});
   // ...
};

The combination of anonymous struct and template function didn't work in VS 2019, so I had to write:

struct Dummy {
  int a;
  double b;
};
template <class O>
Dummy F(int i,O o) {
   return {i, o(i)};
}
void foo(int i) {
   auto [a,b]=F(i, [=](int k)->double {return 1.0/k; /*...*/});
   // ...
};

or:

template <class O>
std::tuple<int,double> F(int i,O o) {
   return {i, o(i)};
}
void foo(int i) {
   auto [a,b]=F(i, [=](int k)->double {return 1.0/k; /*...*/});
   // ...
};

Preference:

  • I don't need the return-type struct, and thus I prefer the anonymous variant, and I know that it works for non-template functions.
  • I want the member-names in the struct for documentation purposes, and thus I find the tuple-variant less clear. (This an especially an issue with more members of the same type.)

So, what is the best way to handle this also for template functions?

The error messages were:

  • error C2143: syntax error: missing ';' before 'identifier'
  • error C2332: 'struct': missing tag name
  • error C3306: '': > unnamed class template is not allowed

Solution 1:

How about local struct:

template <class O>
auto F(int i, O o) {
    struct {
        int a;
        double b;
    } res {i, o(i)}; 
   return res;
}
void foo(int i) {
   auto [a,b] = F(i, [=](int k)->double {return 1.0/k; /*...*/});
   // ...
};

Demo

Solution 2:

I would suggest to use std::tuple (or std::pair in this case). E.g.

#include<tuple>

template <class O>
auto F(int i,O o) {
   return std::tuple{i, o(i)};
}
void foo(int i) {
   auto [a,b]=F(i, [=](int k)->double {return 1.0/k; /*...*/});
   // ...
};