anything special about double so it cannot make constexpr work?
ints and doubles behave differently in this case.
For core constant expression, a in the 2nd case (with type int) is usable in constant expressions , but a in the 1st case (with type double) isn't.
A core constant expression is any expression whose evaluation would
  not evaluate any one of the following:
- 
- an lvalue-to-rvalue implicit conversion unless.... - 
- a. applied to a non-volatile glvalue that designates an object that is usable in constant expressions (see below), - int main() {
    const std::size_t tabsize = 50;
    int tab[tabsize]; // OK: tabsize is a constant expression
                      // because tabsize is usable in constant expressions
                      // because it has const-qualified integral type, and
                      // its initializer is a constant initializer
    std::size_t n = 50;
    const std::size_t sz = n;
    int tab2[sz]; // error: sz is not a constant expression
                  // because sz is not usable in constant expressions
                  // because its initializer was not a constant initializer
}
 
 
 
and
(emphasis mine)
Usable in constant expressions In the list above, a variable is usable
  in constant expressions if it is
- a constexpr variable, or
- it is a constant-initialized variable
  
  
- of reference type or
- of const-qualified integral or enumeration type.
 
You can declare a as constexpr to make it usable in constant expression. e.g.
constexpr double a = 1.0;
constexpr double b = a;   // works fine now