gpt4 book ai didi

c++ - 带有别名的 SFINAE,重载问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:02:24 25 4
gpt4 key购买 nike

我有这段代码:

#include <iostream>
#include <type_traits>

template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
using FloatingPoint = T;

template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
using Integral = T;

template <typename T> void f(Integral<T>) { std::cout << "integral" << std::endl; }

template <typename T> void f(FloatingPoint<T>) {
std::cout << "floating point" << std::endl;
}

int main() {
f(5);
return 0;
}

此代码无法编译:

prog.cc:12:28: error: redefinition of 'f'
template <typename T> void f(FloatingPoint<T>) {
^
prog.cc:10:28: note: previous definition is here
template <typename T> void f(Integral<T>) { std::cout << "integral" << std::endl; }
^
prog.cc:17:3: error: no matching function for call to 'f'
f(5);
^
prog.cc:12:28: note: candidate template ignored: substitution failure [with T = int]
template <typename T> void f(FloatingPoint<T>)

有点奇怪,因为它理解有一个替换失败,但他不想采取第一个重载。

所以我知道两种处理方法。第一件事是将 enable_if 作为参数或返回类型。还有其他方法可以“漂亮”地处理这个问题吗?或者我必须使用我之前写的两个解决方案之一吗?

目标是编写干净的代码。我喜欢使用 C++20 中的概念,但它似乎还不可能在所有地方使用(我指的是 GCC、Clang 和 MSVC)https://en.cppreference.com/w/cpp/compiler_support .或者这个网站不是最新的并且 MSVC (2019)、GCC 10 和 clang 9 都支持良好的概念?

最佳答案

我认为你的问题是 FloatingPointIntegral 直接依赖于 T。重新组织你的代码你可以得到以下内容。您可以在此处运行代码:https://onlinegdb.com/By-T4bBfB .

#include <iostream>
#include <type_traits>

template<typename T>
using isFloatingPoint = std::enable_if_t<std::is_floating_point_v<T>, bool>;

template<typename T>
using isIntegral = std::enable_if_t<std::is_integral_v<T>, bool>;


template <typename T, isIntegral<T> = true>
void f(T) {
std::cout << "integral" << std::endl;
}

template <typename T, isFloatingPoint<T> = true>
void f(T) {
std::cout << "floatingPoint" << std::endl;

}

int main() {
f(5);
f(5.0);
}

或者,如果您使用的是 C++17,则可以使用 if constexpr。你说这在评论中是不可扩展的。在我看来是的,但很可能我不理解你所受的约束。为此,请参阅 https://godbolt.org/z/gLc7YE . if constexpr 允许您非常轻松地只有一个函数甚至不同的返回类型。

#include <type_traits>
#include <string>

template<typename T>
auto f(T){
if constexpr (std::is_floating_point_v<T>){
return 0.0f;
}
else if constexpr (std::is_integral_v<T>){
return 0;
} else {
return 0.0;
}
}

int main() {
static_assert(std::is_same_v<decltype(f(5)), int>, "ERROR 1");
static_assert(std::is_same_v<decltype(f(5.0)), float>, "ERROR 2");
static_assert(std::is_same_v<decltype(f(std::string{"JJ"})), double>, "ERROR 3");
return 0;
}

最后我还要指出,在您的代码中为两个 f() 使用不同的返回类型将解决您的问题(在此处运行代码:https://onlinegdb.com/By-9HZrMS):

#include <iostream>
#include <type_traits>

template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
using FloatingPoint = T;

template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
using Integral = T;

template <typename T> int f(Integral<T>) { std::cout << "integral" << std::endl; return 0;}

template <typename T> float f(FloatingPoint<T>) {
std::cout << "floating point" << std::endl;
return 0.0f;
}

int main() {
f(5);
f(5.0);
return 0;
}

关于c++ - 带有别名的 SFINAE,重载问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57169533/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com