我有兩個列舉
#include <iostream>
enum class E1 : unsigned int
{
E11 = 1
};
enum class E2 : unsigned int
{
E21 = 1
};
1在這種情況下,它們具有相同的基礎值 ( )。接下來,我有一個類C,它有兩個模板引數,一個整數j和一個itype的值auto。
template<int j, auto i>
struct C
{ C() { std::cout << "none\n"; } };
我想對這兩個部分進行部分專業化E1::E11,E2::E21就像這樣:
template<int j>
struct C<j, E1::E11>
{ C() { std::cout << j << "E11\n"; } };
template<int j>
struct C<j, E2::E21>
{ C() { std::cout << j << "E21\n"; } };
為了完整起見,這里主要實體化兩個物件:
int main()
{
C<0,E1::E11> e11;
C<1,E2::E21> e21;
return 0;
}
上面的代碼在 gcc 和 icc 上作業得很好,可以在Godbolt 上驗證(完整代碼)
但是任何其他編譯器(clang,msvc)都會失敗。帶有以下訊息
<source>:27:18: error: ambiguous partial specializations of 'C<0, E1::E11>'
C<0,E1::E11> e11;
^
<source>:18:8: note: partial specialization matches [with j = 0]
struct C<j, E1::E11>
^
<source>:22:8: note: partial specialization matches [with j = 0]
struct C<j, E2::E21>
我很清楚為什么會發生這種情況。不過,我似乎無法回答的問題是,是否有可能以標準兼容的方式解決這個問題(如果這是一些 gcc 或 icc 功能),或者是否有針對失敗編譯器的解決方法(clang、msvc)。
順便提一句。如果我洗掉int j模板引數并讓auto i代碼與所有編譯器一起編譯。
提前致謝,
阿諾
uj5u.com熱心網友回復:
auto模板引數可以替換為
template<int j,typename T,T i>
struct C
{ C() { std::cout << "none\n"; } };
如果您可以輸入更多型別,則可以顯式指定列舉的型別:
#include <iostream>
enum class E1 : unsigned int
{
E11 = 1
};
enum class E2 : unsigned int
{
E21 = 1
};
template<int j,typename T,T i>
struct C
{ C() { std::cout << "none\n"; } };
template<int j>
struct C<j,E1, E1::E11>
{ C() { std::cout << j << "E11\n"; } };
template<int j>
struct C<j,E2, E2::E21>
{ C() { std::cout << j << "E21\n"; } };
int main()
{
C<0,E1,E1::E11> e11;
C<1,E2,E2::E21> e21;
return 0;
}
為了減少打字,您可以使用輔助功能:
template <int j,auto i>
auto make_C(){
return C<j,decltype(i),i>();
}
int main()
{
auto e11 = make_C<0,E1::E11>();
auto e21 = make_C<1,E2::E21>();
}
...或型別特征:
template <int j,auto i>
struct C_helper {
using type = C<j,decltype(i),i>;
};
int main()
{
C_helper<0,E1::E11>::type e11;
C_helper<1,E2::E21>::type e21;
}
uj5u.com熱心網友回復:
在您的情況下,msvc/clang 似乎存在部分專業化問題:(
作為解決方法,您可以將引數拆分為 2 個類:
template <auto i>
struct EC
{
template <int j>
struct C
{
C() { std::cout << "none\n"; }
};
};
template <>
struct EC<E1::E11>
{
template <int j>
struct C
{
C() { std::cout << j << "E11\n"; }
};
};
// Same for E2::E21
然后
EC<E1::E11>::C<0> e11;
EC<E2::E21>::C<0> e21;
演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/433972.html
下一篇:如何擴展初始化串列引數包?
