簡體   English   中英

具有可變參數模板包的類模板的輸出運算符

[英]Output operator for class template with variadic template pack

我試圖按如下所示編寫模板類和輸出運算符:

#include <iostream>

namespace N
{

template< typename ...types >
struct X
{
    static_assert((sizeof...(types) != 0), "zero length");
    X() = default;
    X(X const &) = default;
    X(X &&) = default;
    template< typename ...args >
    //explicit // does not matter
    X(args &&...) { ; }
    int value = 10;
};

template< typename ...types >
std::ostream &
operator << (std::ostream & out, X< types... > const & x)
{
    return out << x.value;
}

} // namespace N

int main()
{
    using namespace N;
    X< float > /*const*/ x; // `const` does not matter
    std::cout << x << std::endl;
    return 0;
}

但是static_assert離子提出了:

main.cpp:9:5: error: static_assert failed "zero length"
    static_assert((sizeof...(types) != 0), "zero length");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:32:23: note: in instantiation of template class 'N::X<>' requested here
    std::cout << x << std::endl;
                      ^
1 error generated.

如果在全局namespace定義了類模板Xoperator <<重載,則所有內容都是相同的。 我發現, using namespace N;注釋using namespace N; X< float >替換為N::X< float >解決此問題。

如何解釋這種行為? 原因是什么?

編輯:

我找到了解決方案:如下對operator <<重載進行模板參數修改:

template< typename first, typename ...rest >
std::ostream &
operator << (std::ostream & out, X< first, rest... > const & x)
{
    return out << x.value;
}

typename ..types分類的typename ..types 此外,由於極端的代碼膨脹會導致后果,因此根本不希望這樣做。

重現問題的簡單方法:

int main()
{
    using namespace N;
    std::cout << std::endl;
}

在這種情況下,候選函數都是std::ostream namespace stdoperator<<所有重載, std::ostream來自所有成員operator <<的,而namespace N函數模板operator<<

13.3.1 / 7:“如果候選對象是功能模板,則使用模板參數推導來生成候選功能模板專業化”

因此,在開始重載解析之前,必須從std::endl推斷出X<types...> const& ,這是模板函數的地址。 函數的地址是函數指針類型,將N::X<types...> const&匹配到指針類型的唯一方法是將types...推導出為空列表。

(替換當然會失敗,因為沒有從任何函數指針類型到N::X<>隱式轉換,這會以不可行的方式靜默消除重載,但靜態斷言不在立即上下文中並且是一個硬錯誤)

故事的寓意: 使用指令是邪惡的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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