15

I have a function foo that takes a variadic function pointer as its argument.

I would like to use "using" to define the argument's type prior to the function declaration.

template <typename ... vARGS>
using TFuncType = void(*)(vARGS ... V_args);

template <typename ... vARGS>
void foo(TFuncType<vARGS ...> funcptr) {}

void bar(int i) {}

int main() {
  foo(&bar); // This line fails to compile.
}

This doesn't compile. The error (via clang using c++1z) is:

/make/proj/test/variadic-funcparam-deduce2.cpp:39:5: error: no matching function for call to 'foo'
foo(&bar);
^~~
/make/proj/test/variadic-funcparam-deduce2.cpp:33:36: note: candidate template ignored: substitution failure [with vARGS = int]
template <typename ... vARGS> void foo(TFuncType<vARGS ...> funcptr) {}

Why is the "int" substitution failing?

I can successfully compile if I explicitly write the type inside foo():

template <typename ... vARGS>
void foo(void(*funcptr)(vARGS ... V_args)) {}

But I cannot get the initial ("using") version to work even when explicitly specifying the template parameters, and using a pre-casted TFuncType<int> for the argument, i.e.:

int main() {
  TF_call<int> fptr = &bar; // This line is OK.
  foo<int>(fptr);
}

Does anyone know what's up here?

Is there something strange about using typedef'd ("using") variadics and/or function pointers that I'm missing?

Zohaib Ijaz
  • 21,926
  • 7
  • 38
  • 60
xaxazak
  • 748
  • 4
  • 16
  • 5
    Works with GCC, and I can't think of any rule this code breaks, so I'm going to go with a Clang bug. – T.C. Jul 04 '15 at 23:33
  • Ok, I'll leave it for an hour or so then file a bug report if no further comments. Thanks. – xaxazak Jul 04 '15 at 23:47
  • I sent this through clang 3.6 via -std=c++14 without issue. Fyi, Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) – WhozCraig Jul 05 '15 at 00:22
  • Just doing a trunk update now so I can retest before reporting. I think it was around 2 months old, but a bit hard to check at the moment. I believe it was with 3.7.0, via trunk. – xaxazak Jul 05 '15 at 00:22
  • For me: fails with clang release 3.4, 3.5, 3.6; works with gcc 4.7, 4.8, 4.9. Looks legal to me, too. – o11c Jul 05 '15 at 00:25
  • also fails with trunk 241397 (3.7.0, a few hours ago). will submit bug. – xaxazak Jul 05 '15 at 02:59
  • Ok, I submitted bug, but I got to wondering: Is this the same issue as my previous question (http://stackoverflow.com/questions/29945432/c-correct-syntax-for-friending-a-template-type-member-of-template-parameter). Basically, is the compiler not _supposed_ to do reverse lookups on variadic typedefs. Maybe GCC's accepting invalid. – xaxazak Jul 05 '15 at 03:34
  • 4
    This is definitely a Clang bug; a debug build of Clang asserts on this code. – Richard Smith Jul 06 '15 at 00:40
  • I have a bug report here: https://llvm.org/bugs/show_bug.cgi?id=24032. However, I'm waiting on responses. I'm unconvinced that it's clang getting it wrong, rather than GCC wrongly accepting it. An earlier question I posted (http://stackoverflow.com/questions/29945432) has a related issue with reverse-lookups on variadic typedefs. – xaxazak Jul 08 '15 at 23:23
  • Interestingly enough, ICC 13 [rejects this code too](http://goo.gl/bg52PH) – LThode Dec 14 '15 at 18:24

1 Answers1

1

I believe this may be related to the following text which I copied from this answer that itself takes from the C++ standard in 14.5.7 [temp.alias] paragraph 2:

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template. [ Note: An alias template name is never deduced. — end note ]

If I'm interpreting that right, it means that GCC accepting the code is actually non-conforming.

Community
  • 1
  • 1
Kurt Stutsman
  • 3,994
  • 17
  • 23
  • Yeah, I'm pretty sure now that it's illegal. Your snippet seems to explain it, thanks. – xaxazak Feb 29 '16 at 14:47
  • I'm not so sure. It says an alias template *name* is never deduced. It's not deducing the name, because the name is already given in the declaration of the template function. That caveat only seems to apply if your template expects a _template template_ parameter. See [the cppreference example](http://en.cppreference.com/w/cpp/language/template_argument_deduction#Alias_templates) – Tim Yates Jun 05 '16 at 13:25