title: Is it possible to assign and verify a constexpr structure in C++14?
body: <p>I implemented a <a href="https://github.com/m2osw/advgetopt" rel="nofollow noreferrer"><code>getop()</code> in C++</a>. This is a class with all sorts of bells and whistles.</p>
  
  <p>One of those bells would be a way to verify that the user enters valid options at compile time. Already I have part of that for the flags (not shown here) but I've been trying to make it work for the <code>struct option</code> and at this time I've not had much success.</p>
  
  <p>First of all, the code allows me to define an array of options using  the <code>define_option()</code> function. I want to be able to specify the fields of the option structure in any order and have some sanity checks on them. So I use a list of arguments to a template function. Each argument is a class which gets instantiated on the spot and then the <code>define_option()</code> selects the correct class for each field, extracting the value.</p>
  
  <p>Up to here, everything works like a charm. Pretty basic C++.</p>
  
  <p>Where I'm having a problem is inside the <code>define_option()</code> class. Say for instance that I were to try the following:</p>
  
  <pre><code>... define_option(...)
  {
      ...
      option opt = { ... };
      static_assert(opt.f_short_name != '\0', "this failed");
      ...
  }
  </code></pre>
  
  <p>Here I get an error. <code>static_assert()</code> tells me that <code>opt</code> is not constant.</p>
  
  <blockquote>
    <p>a.cpp:168:1: error: non-constant condition for static assertion</p>
  </blockquote>
  
  <p>So next my step is to mark the <code>opt</code> variable a <code>constexpr</code> (something the error says to do to resolve the <code>static_assert()</code>.)</p>
  
  <pre><code>... define_option(...)
  {
      ...
      constexpr option opt = { ... };
      ...
  }
  </code></pre>
  
  <p>Now even without the <code>static_assert()</code>, the code doesn't compile. I get the following error:</p>
  
  <blockquote>
    <p>a.cpp:168:5: error: ‘args#0’ is not a constant expression</p>
  </blockquote>
  
  <p>I'm thinking that it's not really doable from within the <code>define_option()</code> function, even though it's possible to check the resulting list of options as shown in the working example below. So in the end the <code>opt</code> global variable is a static fully defined at compile time (no code necessary to re-work on the table at runtime) but that doesn't help me since I can't make sure that the arguments for each option will work as expected.</p>
  
  <p>I have an <a href="http://coliru.stacked-crooked.com/a/303d372ab27e4ba6" rel="nofollow noreferrer">online running sample</a> on coliru.</p>
  
  <pre><code>// compiled with: g++ -std=c++14 -o a ~/tmp/a.cpp
  //
  #include &lt;iostream&gt;
  
  typedef char32_t            short_name_t;
  constexpr short_name_t      NO_SHORT_NAME = L'\0';
  
  struct option
  {
      short_name_t        f_short_name = NO_SHORT_NAME;
      char const *        f_name = nullptr;
  };
  
  
  template&lt;typename T, T default_value&gt;
  class OptionValue
  {
  public:
      typedef T   value_t;
  
      constexpr OptionValue&lt;T, default_value&gt;()
          : f_value(default_value)
      {
      }
  
      constexpr OptionValue&lt;T, default_value&gt;(T const v)
          : f_value(v)
      {
      }
  
      constexpr value_t get() const
      {
          return f_value;
      }
  
  private:
      value_t     f_value;
  };
  
  
  class ShortName
      : public OptionValue&lt;short_name_t, NO_SHORT_NAME&gt;
  {
  public:
      constexpr ShortName()
          : OptionValue&lt;short_name_t, NO_SHORT_NAME&gt;()
      {
      }
  
      constexpr ShortName(short_name_t name)
          : OptionValue&lt;short_name_t, NO_SHORT_NAME&gt;(name)
      {
      }
  };
  
  
  class Name
      : public OptionValue&lt;char const *, nullptr&gt;
  {
  public:
      constexpr Name()
          : OptionValue&lt;char const *, nullptr&gt;()
      {
      }
  
      constexpr Name(char const * name)
          : OptionValue&lt;char const *, nullptr&gt;(name)
      {
      }
  };
  
  
  template&lt;typename T, typename F, class ...ARGS&gt;
  constexpr typename std::enable_if&lt;std::is_same&lt;T, F&gt;::value, typename T::value_t&gt;::type find_option(F first, ARGS ...args)
  {
      return first.get();
  }
  
  
  template&lt;typename T, typename F, class ...ARGS&gt;
  constexpr typename std::enable_if&lt;!std::is_same&lt;T, F&gt;::value, typename T::value_t&gt;::type find_option(F first, ARGS ...args)
  {
      return find_option&lt;T&gt;(args...);
  }
  
  
  
  template&lt;class ...ARGS&gt;
  constexpr option define_option(ARGS ...args)
  {
      option opt =
      {
          .f_short_name =          find_option&lt;ShortName   &gt;(args..., ShortName()),
          .f_name =                find_option&lt;Name        &gt;(args...),
      };
  
      return opt;
  }
  
  
  constexpr option const opt[] =
  {
      define_option(
          Name("--help"),
          ShortName('h')
      )
  };
  
  
  // this test works as expected here
  // but it does not work from inside define_option()
  //
  static_assert(opt[0].f_name[0] != '-', "Wrong start?!");
  
  int main(int argc, char * argv [])
  {
  
      std::cerr &lt;&lt; "opt[0].f_short_name = " &lt;&lt; opt[0].f_short_name &lt;&lt; std::endl;
  
      return 0;
  }
  </code></pre>
  
  <p>At this time I'm limited to C++14. If there is a C++17 solution, I'd still be interested.</p>