![](/img/trans.png)
[英]Changing return type of a function without template specialization. C++
[英]Specialization of function template without changing its prototype
假設A
是某個類,我有以下帶有非類型參數的函數模板:
template <typename T, int v> void func(const T& x);
現在我希望對不同類型的T
有不同的實現,例如我想有一個通用版本的func
用於通用類型(通用意味着類型沒有為其設計的特殊版本的func
)和一個特殊版本的func
用於類A
這與一般版本不同。 此外,此設計的用戶通過以下方式調用func
:
func<int,9>(11);
func<A,1>(a); //a is an object of class A
我的問題是,鑒於函數模板不允許部分專門化並且重載func
不允許用戶以func<A,1>
的方式調用它,我如何才能正確實現func
?
只需讓類型系統為您完成工作:
#include <iostream>
class A {};
// Default implementation
template <typename T, int v> void func(const T& x)
{
std::cout << x + v << "\n";
}
// Specialized for A
template <typename T, int v> void func(const A& x) //<-- matches A for argument T
{
std::cout << "Groovy " << v << "\n";
}
int main()
{
func<int, 9>(11);
func<double, 3>(0.14159);
func<const char*, 3>("uh oh!");
func<A, 1>(A());
}
輸出:
20
3.14159
oh!
Groovy 1
現場示例在這里
您可以使用 C++20概念來做到這一點:
#include <concepts>
struct A {};
template <typename T, int v>
void func(const T& x) {
// general version
}
template <std::same_as<A> T, int v>
void func(const T& x) {
// special version
}
您可以使用std::enable_if
執行您想要的操作,如下所示:
#include <iostream>
#include <iostream>
class A
{
};
template <typename T, int v> void func(const T&x) //primary template
{
std::cout<<"primary template"<<std::endl;
}
template <typename T,int v, typename = std::enable_if<std::is_same<T, A>::value>> void func(const A&x)
{
std::cout<<"choosen for A"<<std::endl;
}
int main()
{
A a;
func<int, 9>(11); //prints primary template
func<A, 9>(a); //prints choosen for A
return 0;
}
盡管稻田的回答綽綽有余。 此外,上述版本允許編寫func<void, 9, int*>(a);
你可能不想要。
如果您只想處理A
並且不需要自定義點,從 C++17 開始,您可以使用if conxtexpr
:
template <typename T, int v>
void func(const T& x)
{
if constexpr (std::is_same_v<T, A>) {
// specific code for A
} else {
// generic code: Not a A
}
}
否則,您可以將實現委托給您可以自定義的其他函子/函數:
template <typename T, int v>
struct func_impl
{
void operator()(const T&) const { /* Generic code */ }
};
template <typename T, int v> void func(const T& x)
{
func_impl<T, v>{}(x);
}
// Customization part
class A;
template <int v>
struct func_impl<A, v>
{
void operator()(const A&) const { /* Specific code for A */ }
};
或者
// Allow both parameters to be deducible, to ease the possibility to overload
// on any part.
template <typename T, int v>
void func_impl(std::integral_constant<int, v>, const T& x)
{
// Generic code
}
template <typename T, int v> void func(const T& x)
{
func_impl(std::integral_constant<int, v>{}, x);
}
// Customization point (with ADL)
class A;
template <int v>
void func_impl(std::integral_constant<int, v>, const A& x)
{
// Specific code for A.
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.