Why is this C++ explicit template specialization code illegal?

(Note: I know how it is illegal, I'm looking for the reason that the language make it so.)

template void Foo();  // Note: no generic version, here or anywhere.

int main(){
  Foo();
  return 0;
}

template<> void Foo();

Error:

error: explicit specialization of 'Foo' after instantiation

A quick pass with Google found this citation of the spec but that offers only the what and not the why.

Edit:

Several responses have forwarded the argument (e.g. confirmed my speculation) that the rule is this way because to do otherwise would violate the One Definition Rule (ODR). However, this is a very weak argument because it doesn't hold, in this case, for two reaons:

  1. Moving the explicit specialization to another translation unit solves the problem and doesn't seem to violate the ODR (or so the linker says).
  2. The short form of the ODR (as applied to functions) is that you can't have more than one body for any given function, and I don't. The only place the body of the function is ever defined is in the explicit specialization, so the call to Foo can't define a generic specialization of the template because there is no generic body to be specialized.

Speculation on the matter:

A guess as to why the rule exist at all: if the first line offered a definition (as opposed to a declaration), an explicit specialization after an instantiation would be a problem because you would get multiple definitions. But in this case, the only definition in sight is the explicit specialization.

Oddly the following (or something like it in the real code I'm working on) works:

File A:

template void Foo();

int main(){
  Foo();
  return 0;
}

File B:

template void Foo();

template<> void Foo();

But to use that in general starts to create a spaghetti imports structure.

7
задан BCS 3 May 2011 в 21:42
поделиться