我有一個模板類,我想專門針對整數型別使用其中一種方法。我看到很多使用enable_iftrait 為模板化函式執行此操作的示例,但我似乎無法獲得在類方法上執行此操作的正確語法。
我究竟做錯了什么?
#include <iostream>
using namespace std;
template<typename T>
class Base {
public:
virtual ~Base() {};
void f() {
cout << "base\n";
};
};
template<typename Q>
void Base<std::enable_if<std::is_integral<Q>::value>::type>::f() {
cout << "integral\n";
}
template<typename Q>
void Base<!std::enable_if<!std::is_integral<Q>::value>::type>::f() {
cout << "non-integral\n";
}
int main()
{
Base<int> i;
i.f();
Base<std::string> s;
s.f();
return 0;
}
上面的代碼無法編譯:
main.cpp:16:60: error: type/value mismatch at argument 1 in template parameter list for ‘template class Base’
16 | void Base<std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^
main.cpp:16:60: note: expected a type, got ‘std::enable_if<(! std::is_integral<_Tp>::value)>::type’
main.cpp:21:61: error: type/value mismatch at argument 1 in template parameter list for ‘template class Base’
21 | void Base<!std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^
main.cpp:21:61: note: expected a type, got ‘! std::enable_if<(! std::is_integral<_Tp>::value)>::type’
main.cpp:21:6: error: redefinition of ‘template void f()’
21 | void Base<!std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:16:6: note: ‘template void f()’ previously declared here
16 | void Base<std::enable_if<!std::is_integral<Q>::value>::type>::f() {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uj5u.com熱心網友回復:
另一種選擇是if constexpr(C 17):
template<typename T>
class Base
{
public:
virtual ~Base() = default;
void f() {
if constexpr(std::is_integral<T>::value) {
std::cout << "integral\n";
} else {
std::cout << "non-integral\n";
}
}
};
uj5u.com熱心網友回復:
您的代碼需要一些修復。
首先,這不是部分專業化。如果是專門化,那么您只能專門化整個類模板,而不僅僅是它的一種方法。
你放!錯地方了。std::enable_if<....>::type是一種型別,!std::enable_if<....>::type沒有意義。您想啟用一個功能 whenstd::is_integral<T>::value和另一個 if !std::is_integral<T>::value。
您可以像這樣撰寫兩個多載:
#include <iostream>
using namespace std;
template<typename T>
class Base {
public:
virtual ~Base() {};
template<typename Q = T>
std::enable_if_t<std::is_integral<Q>::value> f() {
cout << "integral\n";
}
template<typename Q = T>
std::enable_if_t<!std::is_integral<Q>::value> f() {
cout << "non-integral\n";
}
};
int main()
{
Base<int> i;
i.f();
Base<std::string> s;
s.f();
return 0;
}
SFINAE 在回傳型別上。Q只是有一個模板引數(SFINAE 需要)。要么std::is_integral<T>::value是true要么不是,只有兩個多載中的一個不是替換失敗。如果不是替換失敗,std::enable_if_t< ...>則為void。
uj5u.com熱心網友回復:
SFINAE 在這里幫不了你,因為f它不是模板函式。
不過,您可以為此使用概念。使用此功能需要 C 20:
#include <iostream>
#include <concepts>
template<typename T>
class Base {
public:
~Base() {};
void f() requires std::integral<T>
{
std::cout << "integral\n";
}
void f() requires !std::integral<T>
{
std::cout << "non-integral\n";
}
};
uj5u.com熱心網友回復:
這些是多載,而不是專業化。您還需要在類宣告中具有兩個多載,否則您無法撰寫這兩個宣告。那時,最好將函式體放在class宣告中;SFINAE 保證其中只有一個處于活動狀態。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/529535.html
標籤:C 模板
