2

I would like to be able to introspect whether or not a function or function object may be called at compile time; that is, whether or not it is constexpr:

template<class Function>
struct is_constexpr;

This is my first attempt, which does seem to work, but may not generalize:

#include <type_traits>
#include <iostream>

template<class Function>
struct is_constexpr
{
  template<class T,
           int = (T()(), 0)>
  static std::true_type test(const T& f);

  static std::false_type test(...);

  static const bool value = decltype(test(Function()))::value;
};

struct is_constexpr_function
{
  constexpr void operator()() const
  {
  }
};

struct is_not_constexpr_function
{
  void operator()() const
  {
  }
};

int main()
{
  std::cout << "is_constexpr_function is constexpr function object: " << is_constexpr<is_constexpr_function>::value << std::endl;
  std::cout << "is_not_constexpr_function is constexpr function object: " << is_constexpr<is_not_constexpr_function>::value << std::endl;
}

Program output:

$ clang -std=c++14 is_constexpr.cpp -lstdc++
$ ./a.out 
is_constexpr_function is constexpr function object: 1
is_not_constexpr_function is constexpr function object: 0

Is this possible to do correctly in C++? If so, what might a correct implementation of is_constexpr look like? If not, what approximations might be possible?

Jared Hoberock
  • 11,118
  • 3
  • 40
  • 76
  • 1
    Note that the reason yours doesn't work is that you're simply checking if the function is invocable - nowhere do you actually require that its invocable *as a constant expression*. – Barry Dec 13 '17 at 20:00
  • 1
    This isn't currently possible in standard C++. I think there's a proposal floating around for a `constexpr` operator which asks "is this expression `constexpr`?" For what you can use right now, with clang and g++, you may be able to use [`__builtin_constant_p()`](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html) to do what you want, but that also takes compiler optimizations into account. – Justin Dec 13 '17 at 20:02
  • 1
    Actually this code does not check whether function is invocable at all since it is only used inside of `decltype` which does not evaluate anything. – user7860670 Dec 13 '17 at 20:02
  • 1
    @VTT Yes, it does. The check verifies that the expression itself is valid. For instance, try `is_constexpr_function`. – Barry Dec 13 '17 at 20:12
  • Thanks for your replies. I've updated the original post with a corrected implementation that seems to do what I want. However, @Justin's comment indicates that this isn't currently possible in C++. Is there some case which my implementation will not handle correctly? – Jared Hoberock Dec 13 '17 at 21:45
  • 1
    @JaredHoberock It turns out I was wrong. There's a way to do it by "abusing" the `noexcept` operator, as shown in [the accepted answer of the marked duplicate](https://stackoverflow.com/a/46920091/1896169). The proposed `constexpr` operator would be able to do a bit more, but this may be all you desire – Justin Dec 13 '17 at 21:47
  • 1
    @Barry - Sorry: are you sure this is a duplicate of the question you pointed? Is seems to me that this question (simplifying) is "how detect if a function is callable as `constexpr`?" where the other is (ever simplifyng) "how detect when a `constexpr` function is executed compile time and when is executed runtime?". Maybe I'm wrong (I've big troubles with English) but It seems to me that they are different questions. – max66 Dec 14 '17 at 01:05

0 Answers0