如何使带有转换构造函数的包装器<int>类在重载决策中胜过包装器<double>?

问题描述 投票:0回答:1

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

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
}

但是,当我为

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);
}

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) {
      |      ^~~~

我该如何修复它?

c++ compiler-errors overloading overload-resolution
1个回答
6
投票

使构造函数成为模板,接受任何类型。然后使用 SFINAE 拒绝除

T
以外的类型。这将防止调用时隐式参数转换。

#include <concepts>

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

或 C++20 之前的版本:

template <class T>
struct wrapper {
    template <typename U = T, std::enable_if_t<std::is_same_v<T, U>, int> = 0>
    wrapper(const U &o): value(o) {}
    T value;
};
© www.soinside.com 2019 - 2024. All rights reserved.