如何使带有转换构造函数的wrapper<int>类在重载解析中胜过wrapper<double>?

xuj*_*ujh 3 c++ overloading compiler-errors overload-resolution

我正在尝试设计一个包装器来使用一些特殊逻辑来处理算术参数。

https://godbolt.org/z/zG959e5Pz

#include <stdio.h>

template <class T>
struct wrapper {
    wrapper(const T& o): value(o) {}
    T value;
};

void func(wrapper<int> a) {
    printf("int: %d\n", a.value);
}


int main () {
    func(1); // int: 1
    func(1.0); // int: 1
}
Run Code Online (Sandbox Code Playgroud)

但是,当我声明 的重载函数时func,我遇到了编译错误。编译器似乎无法选择具体的重载函数。

#include <stdio.h>

template <class T>
struct wrapper {
    wrapper(const T& o): value(o) {}
    T value;
};

void func(wrapper<int> a) {
    printf("int: %d\n", a.value);
}

void func(wrapper<double> a) {
    printf("double: %.2f\n", a.value);
}

int main () {
    func(1);
    // func(1.1);
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/YEo4c3E69

编译器错误

<source>: In function 'int main()':
<source>:18:9: error: call of overloaded 'func(int)' is ambiguous
   18 |     func(1);
      |     ~~~~^~~
<source>:9:6: note: candidate: 'void func(wrapper<int>)'
    9 | void func(wrapper<int> a) {
      |      ^~~~
<source>:13:6: note: candidate: 'void func(wrapper<double>)'
   13 | void func(wrapper<double> a) {
      |      ^~~~
Run Code Online (Sandbox Code Playgroud)

我该如何修复它?

Hol*_*Cat 6

使构造函数成为模板,接受任何类型。然后拒绝除TSFINAE 之外的类型。这将防止调用它时隐式参数转换。

#include <concepts>

template <class T>
struct wrapper {
    template <std::same_as<T> U = T>
    wrapper(const U &o): value(o) {}
    T value;
};
Run Code Online (Sandbox Code Playgroud)

或者 C++20 之前的版本:

template <class T>
struct wrapper {
    template <typename U = T, std::enable_if_t<std::is_same_v<T, U>, std::nullptr_t> = nullptr>
    wrapper(const U &o): value(o) {}
    T value;
};
Run Code Online (Sandbox Code Playgroud)

  • 删除的重载**是**候选函数,即使被删除。 (2认同)