This is a C++ only issue. In C, an empty struct is prohibited by the compiler.
In C++, the reason for the sizeof(foo) == 1 is ultimately so that the C++ Standard's rule of "no object shall have the same address in memory as any other variable" can be enforced. You can read the details here.
EDIT: Regarding the comment by user2864740 about baz appearing that it should also be non-zero is correct. The compiler is allowing the empty array which makes it appear that the finessing rule is not being applied consistently to baz like it was to foo. This does, in fact, mess up the pointer arithmetic. See this example:
// C++14 code
#include <iostream>
using namespace std;
int main() {
  struct baz {
    int dummy[1];
  };
  cout << sizeof(baz) << endl;
  baz* arr;
  arr = new baz[5];
  cout << &arr[0] << endl;
  cout << &arr[1] << endl;
  return 0;
}
// everything looks good
4
0x892c008
0x892c00c
But if we take the same code and change the array inside baz to be int dummy[0];, then we get this output:
0
0x8fe3008
0x8fe3008
Dangerous indeed; this could lead to infinite loops. It is recommended you don't be naughty like this even if you've found a way to get away with it :)