How do I call invoke_result correctly for a member function? Or specifically for an operator member function. I tried std::invoke_result<T::operator[], size_type>
to no success. What would be the correct syntax in this case?

- 1,251
- 12
- 29
-
@TedLyngmo I simply thought my code would be misleading, since it would just detract from the main question. `T` here is a template typename anyways, so it should work in general for any class providing an `operator[]` with one argument of `size_t`. – lightxbulb Jul 06 '19 at 01:21
-
I think you underestimate people willing to help. :-) Your code will extremely seldom be mislleading! – Ted Lyngmo Jul 06 '19 at 01:24
-
@TedLyngmo I don't doubt people's willingness to help, I just know I probably wouldn't do a good job of providing a non-misleading minimal example. I've been there, I have done that. It usually turns out bad, because I have irrelevant details in my code which mislead the people trying to answer, so I try my best to provide only the minimal necessary details as of late. – lightxbulb Jul 06 '19 at 01:27
-
@ightxbulb - Ok, let's hope your future at SO will be nice. I get my wrist slapped every now and then - and I've got 40 years in the business. It's not an easy game - but it's worth every minute! – Ted Lyngmo Jul 06 '19 at 01:32
2 Answers
Don't. Use decltype(std::declval<T&>()[size_type{}])
or something similar (adjust the value category and the cv-qualification as needed).
invoke_result
is for when you have an invocable/callable object. You don't have one, so don't try to hammer square pegs into round holes.

- 133,968
- 17
- 288
- 421
-
This works. I assume it doesn't construct T by calling declval though, does it? Since T in this case is quite large. – lightxbulb Jul 06 '19 at 01:02
-
1@lightxbulb `decltype` takes an unevaluated operand. So no, it constructs nothing at runtime. – T.C. Jul 06 '19 at 01:08
-
Does this imply that it constructs it at compile time though (possibly increasing compilation time if there are multiple compile time invocations of this)? – lightxbulb Jul 06 '19 at 10:42
What about as follows ?
std::invoke_result<decltype(&T::operator[]), T, size_type>
But this syntax should works with a single, and not template, operator[]
.
In case of template or overload, you should avoid std::invoke_result
and follows the decltype()
way suggested by T.C.
Or, maybe, you can wrap the call in a lambda function and apply std::invoke_result
to the lambda (if you really, really want to use std::invoke_result
).
Regarding the std::invoke_result
syntax, take in count that a pointer to a member function is a completely different things, compared to a pointer to a regular function. Anyway, you can roughly see it as a pointer to a regular function receiving an additional argument (in first position) corresponding to the object that call its method.
So, in your example, the first T
argument represent the object of type T
that call its operator.

- 65,235
- 10
- 71
- 111
-
I get a `cannot determine which instance of overloaded function ... is intended`. – lightxbulb Jul 06 '19 at 00:57
-
@lightxbulb - I suppose you have more `operator[]` (`const` and not-`const` version?) in your class. – max66 Jul 06 '19 at 00:58
-
@lightxbulb: Perhaps you should update your question with a [mcve] then. – Nicol Bolas Jul 06 '19 at 00:59
-
@max66 There's a const and non-const version of it, yes. No other overload. Is this what's causing the issue? – lightxbulb Jul 06 '19 at 01:00
-
@lightxbulb - yes, I suppose is it. As said: "this syntax should works with a single, and not template, operator[]". To verify, try commenting the non-const version to see if the error disappear. – max66 Jul 06 '19 at 01:06
-
@max66 Yes, this seems to have been a problem, while I couldn't comment out any of the operators since this was breaking the whole code, I tested it by defining a new operator and it turned out it's specifically the const overload causing the issue. T.C.'s answer seems indeed a more adequate solution to what I am trying to do. – lightxbulb Jul 06 '19 at 01:18
-
@lightxbulb - I'm agree. I've tried to explain the syntax for `std::invoke_result` and member functions but I think it's a bad idea to use it to detect the returned type of a specific method. The T.C. solution is, IMHO, a better solution because works also in case of overloading and template methods. – max66 Jul 06 '19 at 01:31
-
@lightxbulb - Anyway, isn't exactly "the const overload causing the issue". There is nothing wrong with the `const` version. The issue is caused by the presence of more than one `operator[]`, so the compiler doesn't know which one choose when you write `decltype(&T::operator[])`. – max66 Jul 06 '19 at 01:34
-
@max66 Is there a specific syntax to invoke specifically the const version in this case? I tried swapping `T` with `const T` to see if it will work, but this didn't produce results. How does one go about resolving such ambiguities? I would assume that one can differentiate between the different overloads through the argument types given, however what can I do for the `const` vs `non-const` case. (I am asking out of curiosity - I do not plan to use this rather than T.C.'s version, but I assume there are cases where `invoke_result` is a valid solution). – lightxbulb Jul 06 '19 at 01:44
-
@lightxbulb - sorry but... if there is a specific syntax, I don't know it. But with T.C. solution, you can add `const` to the `std::declval()` type: `decltype(std::declval
()[size_type{}])` – max66 Jul 06 '19 at 12:19 -
@max66 T.C.'s solution works either way. I was just curious what the correct syntax for resolving the ambiguity would have been for the `invoke_result` version. It's not tragic though. – lightxbulb Jul 06 '19 at 12:20