2017-02-09 58 views
3

考慮this代碼:gcc使用const和模板參數的問題?

#include <type_traits> 

template <int> struct II { }; 
template < const int& > struct RR { }; 

template < template <auto> typename Class, typename Type > struct Check : std::false_type { }; 
template < template <auto> typename Class, auto NonTypes > struct Check<Class,Class<NonTypes>> : std::true_type { }; 

constexpr int TEN = 10; 
constexpr const int& REF = TEN; 

static_assert(Check<II,II<TEN>>::value); // passes 
static_assert(Check<RR,RR<REF>>::value); // FAILS!? 

我用gcc-7.0.1和here就是活生生的例子。問題是如果這是一個編譯器錯誤或者我做錯了什麼?

+0

只是我的猜測:一個普通的'auto'(來自'NonTypes')不能推導出一個引用類型,該類型可以匹配'Class'下推演的const const&'(至少它可以與'const auto&NonTypes' ) –

+0

@PiotrSkotnicki那麼它會適用於'decltype(auto)'嗎? – user975989

+0

@ user975989我認爲匹配一個模板專業化可以歸結爲推導出一個發明的函數模板的類型,其中'decltype(auto)'是沒有用的 –

回答

1

讓我們簡化的例子了一下:

template <template <auto> class C, auto N> 
void foo(C<N>) { } 

int main() { 
    foo(II<TEN>{}); // ok 
    foo(RR<REF>{}); // error 
} 

的問題是正常的auto扣除規則適用於N,它獲取的REF情況推斷鍵入int。非類型模板參數類型 - int const& - 與參數 - int之間存在不匹配,所以它不合格。

如果我們翻轉採取auto const& N(或auto&& N)來代替的例子,那麼它會是II<TEN>通話將被形成不良出於同樣的原因 - 我們現在會得到引用類型,但是一個模板參數參數是一個非參考類型。

您今天的語言不能用一種功能處理兩種情況。你需要兩個:

template <template <auto> class C, auto N>  void foo(C<N>) { } // #1 
template <template <auto&&> class C, auto&& N> void foo(C<N>) { } // #2 

int main() { 
    foo(II<TEN>{}); // ok: calls #1 
    foo(RR<REF>{}); // ok: calls #2 
} 

和你的原始示例相似:你需要一個專業化的值和一個專業化的參考。 C的模板模板非類型參數中的引用可能不是必需的。