llvm / llvm/llvm-project

Clang ignores function templates introduced by using declaration during overload resolution with explicit non-type template arguments

Open
#206,198 5 comments 0 reactions 0 assignees View on GitHub
clang:frontend confirmed
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.