c++ 模板重载方法取决于 class 类型
c++ templates overloading method depend on class type
我有 class 这样的:
template<typename T>
MyClass{
//myFunc();
}
我想创建 myFunc 方法,如果 class 模板是数字,则 return 数值,当 class 模板不是数字时,return 什么都没有(无效)。
现在,我得到了这样的东西:
template<typename T>
MyClass{
template <typename returnT>
returnT myFunc();
}
template <typename T>
template <typename returnT>
typename std::enable_if<std::is_arithmetic<T>::value>
T MyClass<T>::myFunc()
{
return T::value;
}
template <typename T>
template <typename returnT>
typename std::enable_if<!std::is_arithmetic<T>::value>
void MyClass::myFunc()
{
//do sth
}
当然,那是行不通的。以这种方式解决这个问题是个好主意吗?什么是 "smart" 和可行的解决方案?
我能想到的最简单的方法就是使用 if constexpr
:
template <typename T>
class MyClass
{
auto myFunc()
{
if constexpr (std::is_arithmetic_v<T>)
{
return T{};
}
else
{
// do smth
}
}
};
如果你不能使用 C++17,你将不得不恢复到一些基于 SFINAE 的方法。最好的样子在很大程度上取决于所涉及的实际签名应该是什么。但是,例如,您可以为算术类型的情况提供部分 class 模板特化:
template <typename T, typename = void>
class MyClass
{
void myFunc()
{
// do smth
}
};
template <typename T>
class MyClass<T, std::enable_if_t<std::is_arithmetic<T>::value>>
{
T myFunc()
{
return {};
}
};
请注意算术类型不能是 class 类型或枚举,所以我不确定 T::value
在您的示例代码中针对 [=14= 的情况试图实现什么] 算术类型…
作为已提供的 constexpr if
解决方案的替代方案,这里是您的初步想法的工作形式。
#include <type_traits>
#include <iostream>
template<typename T>
struct MyClass{
template <typename returnT = T, std::enable_if_t<std::is_arithmetic_v<returnT>, bool> = true>
T myFunc();
template <typename returnT = T, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool> = true>
void myFunc();
};
template <typename T>
template <typename returnT, std::enable_if_t<std::is_arithmetic_v<returnT>, bool>>
T MyClass<T>::myFunc()
{
std::cout << "yo\n";
return T{};
}
template <typename T>
template <typename returnT, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool>>
void MyClass<T>::myFunc()
{
std::cout << "yay\n";
}
int main() {
MyClass<int> m;
MyClass<std::string> n;
m.myFunc();
n.myFunc();
}
我会创建一个辅助模板 class 到 select return 类型,以及一个使用重载来执行正确行为的辅助函数。
template <typename, bool> struct RType;
template <typename T> struct RType<T, false> { typedef void type; };
template <typename T> struct RType<T, true> { typedef T type; };
template<typename T>
class MyClass{
typedef RType<T, std::is_arithmetic<T>::value> R;
void myFuncT(RType<T, false>) {}
T myFuncT(RType<T, true>) { return 0; }
public:
typename R::type myFunc() { return myFuncT(R()); }
};
我有 class 这样的:
template<typename T>
MyClass{
//myFunc();
}
我想创建 myFunc 方法,如果 class 模板是数字,则 return 数值,当 class 模板不是数字时,return 什么都没有(无效)。
现在,我得到了这样的东西:
template<typename T>
MyClass{
template <typename returnT>
returnT myFunc();
}
template <typename T>
template <typename returnT>
typename std::enable_if<std::is_arithmetic<T>::value>
T MyClass<T>::myFunc()
{
return T::value;
}
template <typename T>
template <typename returnT>
typename std::enable_if<!std::is_arithmetic<T>::value>
void MyClass::myFunc()
{
//do sth
}
当然,那是行不通的。以这种方式解决这个问题是个好主意吗?什么是 "smart" 和可行的解决方案?
我能想到的最简单的方法就是使用 if constexpr
:
template <typename T>
class MyClass
{
auto myFunc()
{
if constexpr (std::is_arithmetic_v<T>)
{
return T{};
}
else
{
// do smth
}
}
};
如果你不能使用 C++17,你将不得不恢复到一些基于 SFINAE 的方法。最好的样子在很大程度上取决于所涉及的实际签名应该是什么。但是,例如,您可以为算术类型的情况提供部分 class 模板特化:
template <typename T, typename = void>
class MyClass
{
void myFunc()
{
// do smth
}
};
template <typename T>
class MyClass<T, std::enable_if_t<std::is_arithmetic<T>::value>>
{
T myFunc()
{
return {};
}
};
请注意算术类型不能是 class 类型或枚举,所以我不确定 T::value
在您的示例代码中针对 [=14= 的情况试图实现什么] 算术类型…
作为已提供的 constexpr if
解决方案的替代方案,这里是您的初步想法的工作形式。
#include <type_traits>
#include <iostream>
template<typename T>
struct MyClass{
template <typename returnT = T, std::enable_if_t<std::is_arithmetic_v<returnT>, bool> = true>
T myFunc();
template <typename returnT = T, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool> = true>
void myFunc();
};
template <typename T>
template <typename returnT, std::enable_if_t<std::is_arithmetic_v<returnT>, bool>>
T MyClass<T>::myFunc()
{
std::cout << "yo\n";
return T{};
}
template <typename T>
template <typename returnT, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool>>
void MyClass<T>::myFunc()
{
std::cout << "yay\n";
}
int main() {
MyClass<int> m;
MyClass<std::string> n;
m.myFunc();
n.myFunc();
}
我会创建一个辅助模板 class 到 select return 类型,以及一个使用重载来执行正确行为的辅助函数。
template <typename, bool> struct RType;
template <typename T> struct RType<T, false> { typedef void type; };
template <typename T> struct RType<T, true> { typedef T type; };
template<typename T>
class MyClass{
typedef RType<T, std::is_arithmetic<T>::value> R;
void myFuncT(RType<T, false>) {}
T myFuncT(RType<T, true>) { return 0; }
public:
typename R::type myFunc() { return myFuncT(R()); }
};