4
#include <iostream>

int foo(int x) {
    if constexpr (std::is_same_v<decltype(x), std::string>) {
        x = std::string();
    }
}

int main(void)
{ return 0; }

This code doesn't compile on either GCC 7 nor Clang 5:

error: cannot convert ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘int’ in assignment
         x = std::string();

Since the referenced line is in a constexpr if branch that should evaluate to false, shouldn't the program compile fine?

Justin
  • 24,288
  • 12
  • 92
  • 142
Maël Nison
  • 7,055
  • 7
  • 46
  • 77
  • This is the expected behavior, surprisingly enough. `if constexpr` doesn't work in this way, only (roughly) for template parameters – Justin Dec 19 '17 at 21:27
  • See [this](https://stackoverflow.com/q/46512248/2069064) or [this](https://stackoverflow.com/q/47000914/2069064) – Barry Dec 19 '17 at 21:30
  • 1
    I do agree with you though. I don't understand why the code you wrote wasn't specified to work. I find it surprising. There are certainly cases where it would be desirable, such as build settings, or target-specific settings – Justin Dec 19 '17 at 21:35
  • @Justin You think it's surprising that assigning a `string` to an `int` doesn't work? I would be curious to see such use-cases... – Barry Dec 19 '17 at 21:45
  • @Barry I guess if I actually think it through, yeah that would be a bug in every case. But there was a couple cases of `if constexpr` that didn't do what I expected, unless I was mistaken. The more I think about it, the more I think I just didn't think it through in those cases.... – Justin Dec 19 '17 at 22:00
  • @Barry preprocessor-generated code, where the action is conditional on the macro types. I know, templates are usually better than macros, but in some circumstances it's just simpler and cleaner to use classic macros. – Maël Nison Dec 20 '17 at 12:31
  • @Justin just where I am right now, with build settings and I found this problem. I am a bit disappointed that if constexpr is limited to template functions only :( – Germán Diago Jan 16 '18 at 08:03

1 Answers1

4

The if constexpr specification defines the discarded statement. It then goes on to define that the discarded statement is not instantiated when the result is not value-dependent after instantiation. The implication is that statements are discarded during template instantiation. Further, the statement is only discarded if the conditional value is dependent on the template arguments.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380