Having read the claim multiple times in articles - I want to add this question to Stackoverflow, and ask the community - is the following code portable?
template<template<typename T, typename Alloc> class C>
void f() {
/* some code goes here ... */
}
int main() {
f<std::vector>();
}
Is the implementation that supplies std::vector
really allowed to have additional, defaulted template parameters beyond the two well known ones? This would render the above code ill-formed, as it assumes two template parameters. See the last paragraph in this article for an example of such a claim.
I found the following issue report, which says
There is no ambiguity; the standard is clear as written. Library implementors are not permitted to add template parameters to standard library classes. This does not fall under the "as if" rule, so it would be permitted only if the standard gave explicit license for implementors to do this. This would require a change in the standard.
The LWG decided against making this change, because it would break user code involving template template parameters or specializations of standard library class templates.
The books and people that say an implementation may add other optional parameters seem to be wrong.
Incredibly, I was recently reading "C++ Templates: The Complete Guide," and last book marked the following on page 111:
A template template argument must be a class template with parameters that exactly match the parameters of the template template parameter it substitutes. Default template arguments of a template template argument are ignored (but if the template template parameter has default arguments, they are considered during the instantiation of the template).
So, if the book is to be believe, your example where non-standard default parameters are added to std::vector would be legal - since default template arguments of a template template argument are ignored.
As a real world test, I compiled the following in g++ (successfully) and Visual Studio 2008 (failed on the mismatched parameters):
template<typename T1, typename T2, typename T3 = float>
class MyClass
{
public:
T1 v1;
T2 v2;
T3 v3;
};
template<template<typename T1, typename T2> class C>
void f()
{
C<int,double> *c = new C<int,double>();
}
int main ()
{
f<MyClass>();
return 0;
}
Check subsubsections of 17.4.4 [lib.conforming].
17.4.4.3/3 says that "a global or non-member function cannot be declared by the implementation as taking additional default arguments", but 17.4.4.4/2 explicitly allows replacing described member function signatures with longer ones so long as the additional parameters have defaults.
There's no section for templates, though, so if they felt the need to provide 17.4.4.3/3, it seems to me like extra template parameters are allowable barring wording to the contrary.
I have seen this claim, too. But.
For one, I have never seen an implementation doing this. I seem to remember that Andrei Alexandrescu once contemplated using things like allocator types on steroids (something like my_fancy_thing<std::allocator,more_info_to_pass_to_the_container>
, while just std::allocator
would still work, too). But even this would still keep your f()
working, and that's the closest thing to an implementation breaking your example I have ever heard being discussed.
I think this falls pretty much into the same category as the claim that a 0
pointer does not necessarily have to be represented by a value with all bits set to zero - even if vendors really have that freedom (which I don't know, since there are claims from both sides, too), they won't ever use it, because that would break basically all existing code.
So I have long since decided to not to worry about it.
来源:https://stackoverflow.com/questions/1469743/standard-library-containers-with-additional-optional-template-parameters