Clang ignores function templates introduced by using declaration during overload resolution with explicit non-type template arguments
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
# Function templates introduced via `using` declaration are ignored during overload resolution with explicit non-type template arguments
## Compiler Version
```
clang version 22.1.0-rc3
Target: x86_64-w64-windows-gnu
Thread model: posix
```
The issue is also reproducible on all Clang versions currently available on Compiler Explorer.
### Compiler Explorer reproducer:
https://godbolt.org/z/4vG1qz6oW
## Minimal reproducer
```cpp
#include
struct Base {
template
void f() {
std::cout << "Base\n";
}
};
struct Derived : Base {
using Base::f;
template
void f() {
std::cout << "Derived\n";
}
};
int main() {
Derived d;
d.f<1>();
}
```
## Expected behavior
The `using Base::f;` declaration introduces both function templates into the overload set.
The explicit template argument `1` is a valid converted constant expression for both `int` and `char`, making both templates viable candidates.
After substitution, both candidates have the same signature:
```cpp
void f();
```
Neither template is more specialized than the other, so overload resolution should report the call as ambiguous.
Both GCC and MSVC reject the program with an ambiguity diagnostic.
## Actual behavior
Clang accepts the program and calls `Derived::f`, apparently ignoring the inherited template introduced by the `using` declaration during overload resolution.
## Related reproducer
The same issue appears when the non-type template parameters have unrelated enum types.
```cpp
#include
enum class E1 { A };
enum class E2 { B };
struct Base {
template
void f() {
std::cout << "Base\n";
}
};
struct Derived : Base {
using Base::f;
template
void f() {
std::cout << "Derived\n";
}
};
int main() {
Derived d;
d.f();
}
```
### Expected behavior
The call should invoke `Base::f`, since only the base template is viable.
GCC and MSVC both compile this program and print:
```
Base
```
### Actual behavior
Clang rejects the program with:
```
error: no matching member function for call to 'f'
note: candidate template ignored: invalid explicitly-specified argument
```
The diagnostic only lists the derived template as a candidate, suggesting that the inherited template introduced by the `using` declaration is not considered.
## Practical impact
I encountered this issue while implementing an event framework that uses inheritance to extend the set of supported events.
A simplified version looks like this:
```cpp
struct Base {
template
void subscribe(...);
};
struct Derived : Base {
using Base::subscribe;
template
void subscribe(...);
};
```
The intended API is:
```cpp
Derived d;
d.subscribe(...);
d.subscribe(...);
```
This works correctly with GCC and MSVC, but with Clang only the derived overloads are accessible unless the base class is explicitly qualified.
## Compiler comparison
| Compiler | First reproducer | Second reproducer |
| -------- | ------------------ | ------------------------------------------------- |
| GCC | Ambiguous | Calls `Base::f` |
| MSVC | Ambiguous | Calls `Base::f` |
| Clang | Calls `Derived::f` | Rejects program; only derived template considered |
Contributor guide
Research direction
Start with the minimal reproducer and the Compiler Explorer example to observe both overload-resolution failures. Investigate Clang's handling of function templates introduced by a using declaration when explicit non-type template arguments are supplied. Done means the two reproducers match the expected GCC and MSVC behavior, including ambiguity for the first and selection of Base::f for the second.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100