2017-08-07 80 views
4

我有一個模板功能,只要做一些事情與給定值作爲模板類型是一個數字:模板函數重載(通用型VS模板模板類型)選擇正確的過載

template <typename scalar_t> 
void function(scalar_t value) 
{ 
    if constexpr (std::is_floating_point_v<scalar_t>) 
    { 
     std::cout << value << 'F'; 
    } 
    if constexpr (std::is_integral_v<scalar_t>) 
    { 
     std::cout << value; 
    } 
} 

和過載的這個模板期待一個容器容納人數:

template <typename scalar_t, template <typename> class container_t> 
void function(const container_t<scalar_t> &container) 
{ 
    for (const auto &value : container) 
    { 
     function(value); 
     std::cout << ' '; 
    } 
} 

通過上面的模板,我叫下面的代碼:

int main() 
{ 
    function('0'); 
    function(short{1}); 
    function(2); 
    function(3l); 
    function(4ll); 
    function(5.f); 
    function(6.); 

    std::vector<int> v{7, 8, 9, 10}; 
    std::list<double> l{11., 12., 13., 14.}; 

    function(v); 
    function(l); 

    return 0; 
} 

其中給出以下輸出:

F6F 

雖然我期待以下輸出:

F6F7 8 9 10 11F 12F 13F 14F 

這意味着第一模板版本(function(scalar_t value))已被選擇,而不是所述第二版本( function(const container_t<scalar_t> &container))。

如何強制爲模板模板參數選擇第二版模板函數?

+0

不知道如果多數民衆贊成的問題,但兩者'VECTOR'和'list'不要有一個,而是兩個模板參數 – user463035818

+0

@ tobi303 [那真是個問題](https://wandbox.org/permlink/kvKHSpDJ6VEOWhRO)如果你能解釋爲什麼在答案中我可以upvote :) –

回答

2

這裏的問題是您的模板類型不匹配。 std::vectorstd::list都有一個分配器的模板參數。 template <typename> class container_t不允許這樣模板不匹配,因此調用void function(scalar_t value)並沒有任何反應。

你需要做的是採取可變模板模板參數。使用

template <typename scalar_t, template <typename...> class container_t> 
void function(const container_t<scalar_t> &container) 
{ 
    for (const auto &value : container) 
    { 
     function(value); 
     std::cout << ' '; 
    } 
} 

你得到

F6F7 8 9 10 11F 12F 13F 14F 

Live Example

+0

有趣的是,'gcc'和'clang'的工作方式與此代碼不同。 'clang'是否正確? –

+0

@EdgarRokyan這很有趣。 AFAIK,鐺在這裏行爲正確。我不確定gcc爲什麼接受它。 – NathanOliver

+1

@EdgarRokyan看起來像是在C++ 14和17之間的gcc中發生了變化。[this](http://coliru.stacked-crooked.com/a/e814e634d60dfeaf)無法在C++ 14模式下編譯,但編譯爲C++ 17模式。現在我不確定是否在C++ 17中發生了某些事情,或者它是gcc的C++ 17實現中的錯誤。 – NathanOliver