3

I have a struct Foo. I would like to add some kind of id (placeholder ?) to statically select from a tuple of values passed to different Foo objects. Ideally I would not make it a template type because it will trigger many changes in other locations.

I tried adding an integer to it and use constexpr expressions (Demo)

#include <tuple>

using namespace std;

struct Foo {
private:
  const int pl;

public:
  constexpr Foo (int c) : pl(c) {}

  constexpr int place() {return pl;}

  template <typename... T>
  constexpr int extract(std::tuple<T ...> const &vals) {
    // I would like to uncomment the following but it fails compiling
    // return std::get<pl>(vals);
    return std::get<0>(vals);
  }
};

int main(void) {
   constexpr Foo f(1);
   constexpr std::tuple<int, int> test = std::make_tuple(0, 10);

   // The following passes
   static_assert(f.place() == 1, "ERROR");
   // The following fails
   static_assert(f.extract(test) == 10, "ERROR");
}

I was expecting that I could use the constexpr place() in the get<>, what am I missing?

Do I have a way out without using templates?

David G
  • 94,763
  • 41
  • 167
  • 253
NickV
  • 1,576
  • 1
  • 10
  • 8
  • 1
    Since `std::get` isn't `constexpr`, I suspect this won't work. http://stackoverflow.com/questions/5087364/how-to-query-a-constexpr-stdtuple-at-compile-time – Nate Kohl Jan 24 '13 at 22:43
  • You're right, as Dave Abrahams says there: "N3305 proposes to add constexpr for tuple::get". Do I have a workaround ? I can go for something else than tuples but I don't really know what atm. – NickV Jan 24 '13 at 22:50
  • Your member functions ought to be `const` as well. – Ben Voigt Jan 25 '13 at 01:16
  • What exactly is your goal? You cannot pass `Foo` by value or reference into a function and then use it to generate a different type when you call `extract`. Now, if you have a bounded set of types in your tuple, it isn't hard to take a run time `int` and auto-write a `switch` that takes either a single multi-type functor or a list of functors that act on each of the types out of the `tuple`. – Yakk - Adam Nevraumont Jan 26 '13 at 15:31

1 Answers1

1

The first blocker is that std::get isn't constexpr, so even if std::get<0> works for you, it doesn't have to. (Credit to @Nate Kohl)

You can try hard and write your own tuple with constexpr accessor, but this approach will fail too. Every function that is constexpr also must be callable without a constexpr argument (or constexpr this). There is currently no way to overload on constexpr.

So, bad luck. This is impossible in C++11.

David G
  • 94,763
  • 41
  • 167
  • 253
ipc
  • 8,045
  • 29
  • 33
  • Well, in my particular case, I am interested in the type of Foo more than the instance. Here is a solution that works but that is going to be nasty to implement int my bigger codebase (http://liveworkspace.org/code/aoBwa$3) – NickV Jan 24 '13 at 23:01
  • I can't think of a nicer way to do that. Sorry. – ipc Jan 24 '13 at 23:13
  • @NickV: (http://liveworkspace.org/code/3uEri9) `std::make_tuple` is not `constexpr` – rici Jan 25 '13 at 00:40
  • @rici: Good catch, thanks. I was relying on the static_assert but it seems it isn't a guarantee of constexpr-ness by itself. – NickV Jan 25 '13 at 04:25