title: Constexpr decltype
body: <p>I recently asked a question here (<a href="https://stackoverflow.com/questions/35231982/detecting-instance-method-constexpr-with-sfinae">Detecting instance method constexpr with SFINAE</a>) where I tried to do some constexpr detection at compile time. Eventually, I figured out that one can exploit <code>noexcept</code> to do this: any constant expression is also <code>noexcept</code>. So I put together the following machinery:</p>
  
  <pre><code>template &lt;class T&gt;
  constexpr int maybe_noexcept(T &amp;&amp; t) { return 0; }
  ...
  constexpr bool b = noexcept(maybe_noexcept(int{}));
  </code></pre>
  
  <p>This works and <code>b</code> is true as you'd expect, as zero-initializing an <code>int</code> is a constant expression. It also correctly yields zero when it should (if I change <code>int</code> to some other appropriate type).</p>
  
  <p>Next, I wanted to check if something is <code>constexpr</code> move constructible. So I did this:</p>
  
  <pre><code>constexpr bool b = noexcept(maybe_noexcept(int(int{})));
  </code></pre>
  
  <p>And again, this works properly for <code>int</code>, or a user defined type. However, this checks that the type has both a constexpr default constructor and a constexpr move constructor. So, to work around this, I tried to change to declval:</p>
  
  <pre><code>constexpr bool b = noexcept(maybe_noexcept(int(declval&lt;int&gt;())));
  </code></pre>
  
  <p>This results in <code>b</code> being false in gcc 5.3.0 (can't use clang for any of this, because clang does not correctly make constant expressions <code>noexcept</code>). No problem, I say, must be because <code>declval</code> is (interestingly enough) not marked <code>constexpr</code>. So I write my own naive version:</p>
  
  <pre><code>template &lt;class T&gt;
  constexpr T&amp;&amp; constexpr_declval() noexcept;
  </code></pre>
  
  <p>Yes, this is naive compared to how the standard library does it as it will choke on void and probably other things, but it's fine for now. So I try again:</p>
  
  <pre><code>constexpr bool b = noexcept(maybe_noexcept(int(constexpr_declval&lt;int&gt;())));
  </code></pre>
  
  <p>This still does not work, <code>b</code> is always false. Why is this not considered a constant expression? Is this a compiler bug, or am I not understanding fundamental about <code>constexpr</code>? It seems like there is some strange interaction between <code>constexpr</code> and unevaluated contexts.</p>