簡體   English   中英

模板類中的模板成員特化

[英]Template member specialization in template class

#include <iostream>
#include <string>

template<typename U>
struct A
{
  template<typename... Ts> auto func();
  template<> auto func<int>();
};

template<typename U>
template<>
auto
A<U>::func<int>() { return std::string{"foo"}; }

int main()
{
  A<float> a{}; 
  std::cout << a.func<int>() << std::endl;
}

這不起作用,因為模板類的模板成員的特化是不可能的,除非您也特化了該類。 (我讀過。)

但是如果你將成員特化的定義移到類定義中,它確實有效:

#include <iostream>
#include <string>

template<typename U>
struct A
{
  template<typename... Ts> auto func();
  template<> auto func<int>() { return std::string{"foo"}; }
};

int main()
{
  A<float> a{};
  std::cout << a.func<int>() << std::endl;
}

我不確定我是否完全理解為什么。 此外,當它使用 clang 時,它不使用 gcc 編譯。 那么哪個是正確的呢?

但我真正的問題是,假設 clang 做對了,為什么這又不起作用:

#include <iostream>
#include <string>

template<typename U>
struct A
{
  template<typename... Ts> auto func();
  template<> auto func<U>() { return std::string{"foo"}; }
};

int main()
{
  A<int> a{};
  std::cout << a.func<int>() << std::endl;
}

這是一個不同的錯誤,不是非專業模板成員的專業化,而是抱怨在定義之前不能使用具有推導返回類型的func<int>

如果我們看一下n4810 § 13.8.3

  1. 成員函數,成員函數模板,成員類,成員枚舉,成員類模板,靜態數據成員或類模板的靜態數據成員模板可以明確地專門用於隱式實例化的類特化; 在這種情況下,類模板的定義應位於類模板成員的顯式特化之前。 如果類模板成員的這種顯式特化指定了一個隱式聲明的特殊成員函數(11.3.3),那么該程序就是格式錯誤的。

但是你可以這樣做,兩者都是專門的:

template<typename U>
struct A
{
  template<typename... Ts> auto func() { /* ... */ }
};

template <>
template <>
auto A<int>::func<int>()
{
  // ok, enclosing class template explicitly specialized
}

雖然這是無效的c ++:

template <typename U>
template <>
auto A<U>::func<int>()
{
  // ops: invalid, enclosing class template not explicitly specialized
}

根據:

  1. 在類模板成員或出現在命名空間作用域中的成員模板的顯式特化聲明中,成員模板及其某些封閉類模板可能保持非專業化,除非聲明不應明確專門化類成員模板封閉類模板也沒有明確專門化。

並且因為:

  1. 明確專門化的函數模板,類模板或變量模板的聲明應在聲明顯式特化之前。

因此,這不應該在外部模板聲明中:

template <typename U>
struct A {
  template<typename...Ts> auto func();
  template<> auto func<int>() { return std::string{"foo"}; } // should not work
};

我不知道為什么clang允許這個。

但是允許它在聲明主模板的命名空間范圍內,在這種情況下是全局命名空間范圍。

這可能是“命名空間”規則的唯一解決方案:

namespace A{
    using TYPE1 = int;
    template<typename>struct A;
    template<>
    struct A<int>{
        using U = int;
        static auto func(){
            return string{"string"};
        };
    };
};
void testFUNC(){
    cout << A::A<A::TYPE1>::func() <<endl;
};

暫無
暫無

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

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