2

Is it possible to write a tester if a template-method with a given signature is defined?

The method is of following signature:

template<typename ReturnType>
ReturnType get(std::string) { return std::declval<ReturnType>(); }

I searched here but all I found were mechanism relying on automated template deduction (e.g. How to test if template function exists at compile time)

user3520616
  • 60
  • 3
  • 17
  • "but all I found were mechanism relying on automated template deduction" - why don't you just use them? – lisyarus Apr 24 '19 at 09:45
  • how would I? Automated template deduction doesn't work in my example because no parameter of the method is of the required Type – user3520616 Apr 24 '19 at 09:46
  • 1
    To clarify: do you want a method to test whether `template get(std::string)` exists, or whether a particular specialization `get(std::string)` can be called? – lisyarus Apr 24 '19 at 09:48
  • 2
    Off topic: you can use `std::declval()` inside a `decltype()`, not in a body of a function. – max66 Apr 24 '19 at 09:48
  • _is defined?_: Does it mean: Is template existing? Is template instanced for this type? Is a function with this signature available (which is not necessarily a template)? Why (for what) do you need this? – Scheff's Cat Apr 24 '19 at 09:48
  • 1
    @lisyarus The second @ Scheff The helper should return true if a function of the signature in my post is defined. It's for better readable error-messages. – user3520616 Apr 24 '19 at 09:54

1 Answers1

4
#include <type_traits>
#include <string>

template <typename T>
constexpr bool test() { return is_invocable<decltype(get<T>), std::string>::value; }

See std::is_invocable. However, test<T> still does not compile if get<T> does not; see comments below.

francesco
  • 7,189
  • 7
  • 22
  • 49
  • Didn't know of this. Most SFINAE stuff documented here is pre c++17; thank you – user3520616 Apr 24 '19 at 10:02
  • 1
    The first argument to `std::is_invocable` is a type, but `get` is not a type: https://wandbox.org/permlink/ySByqAzEuAnxJsRr – lisyarus Apr 24 '19 at 10:11
  • @lisyarus It seems a `decltype()` fixes the suggested solution: [Fixed Demo on Wandbox](https://wandbox.org/permlink/qJNzdwpPIUCpKqsk). – Scheff's Cat Apr 24 '19 at 10:58
  • @Scheff It fails to distinguish between defined & undefined specializations, thus simply checking if `template get (std::string)` exists, which (in my opinion) looks somewhat useless: https://wandbox.org/permlink/FGIlr3lVocP5bFin – lisyarus Apr 24 '19 at 11:29
  • 1
    @lisyarus I agree. That's why my comment how _defined_ is meant precisely... (The example is somehow a bit like Schroedingers Cat: As soon as you check the template it is instanced and hence exists.) ;-) – Scheff's Cat Apr 24 '19 at 11:34
  • @lisyarus Though, "exists" doesn't describe it exactly... [Above Code on godbolt](https://gcc.godbolt.org/z/DefbhU) – Scheff's Cat Apr 24 '19 at 11:40
  • @Scheff Checking godbolt is a hack: compiler optimizations can remove a lot. Anyways, I was too sloppy in my previous comment. There is no such thing as mere *existence* for C++ functions, whether template or not: they can be *declared* and *defined* (and *specialized*, for what it's worth). In our case, the proposed solution checks if `get` was *declared*. – lisyarus Apr 24 '19 at 11:46
  • @user3520616 if you remove the "accepted" I can delete the solution which is not correct. – francesco Apr 24 '19 at 11:47
  • @francesco Why not simply fix it (even if the result is of questionable worth)? At least, you teached two people about the existance of `std::is_invocable()`: the OP and me. ;-) – Scheff's Cat Apr 24 '19 at 11:48
  • @Scheff see the correction, and thanks for the fix! – francesco Apr 24 '19 at 11:53
  • @francesco This still won't compile: you should either declare a template variable via `constexpr bool test = ...`, or declare a constexpr function like `constexpr bool test() { return ... }`. The current version is something in between. – lisyarus Apr 24 '19 at 12:46