簡體   English   中英

函數模板特化,不改變原型

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM