On Sat, 05 Aug 2017 18:42:46 +0200, Marcel Mueller
<
news.5...@spamgourmet.org> wrote:
>On 05.08.17 17.19, Barry Schwarz wrote:
>> In the second case, the same typename (ARGS) is used for both template
>> parameters in the declaration of printMessage. The presence of
>> OPENFAILED as the fist argument of the function call forces the ARGS
>> to be <const char*, const char*> for both parameters. The compiler
>> cannot use this template to generate an instance of the function since
>> the arguments corresponding to parameter a do not both have type const
>> char*. Changing the third argument as described above would produce
>> the same message. It has nothing to do with the existence, or not, of
>> an implicit conversion. If you change the template from ARGS and ARGS
>> to ARGS1 and ARGS2 and use ARGS2 for parameter a, the compiler error
>> disappears.
>
>Hmm, doesn't this disable the type check?
>
>Just tested, it does. With two distinct parameter packs you can pass
>whatever you want, e.g. errno. This will crash the program. So it is not
>an option.
It crashes the program because printMessage is calling printf with a
format string that specified %s and %s. However, the variadic
arguments passed to printf have type char* and int. Passing an int
when printf expects a char* causes undefined behavior. Again, this
has nothing to do with implicit conversions.
Some compilers match printf arguments against the conversion
specifications in the format string. If yours did so, it would have
reported that int is incompatible with the second %s.
>OK I could work around this by forwarding the call to
>MessageTemplate::print, but this is not an option either as it requires
>a member function for every future function that deals with the template
>and the matching parameters. (This is the idea behind the scenes, to
>have different implementations.)
Yes but one of the programmer's responsibilities is to insure that the
code generated when an instance of the template function is created is
valid for the arguments actually passed. It is possible to call many
functions with arguments that are invalid but cannot be detected by
the compiler.