gcc 11.2 似乎無法編譯:
template <typename T = int>
struct Test {};
template <typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test>(t);
}
但沒有問題
template <typename T = int>
struct Test {};
template <typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test<>>(t);
}
這是編譯器錯誤嗎?
這個問題似乎表明它應該作業。
uj5u.com熱心網友回復:
海合會是對的。允許省略函式<>模板的空模板引數串列( [temp.arg.explicit]/4)。在其他情況下,通常需要模板引數串列來命名模板的特定特化,即使它是空的。請參閱simple-template-id的語法[temp.names]/1。
作為規則的一個有限例外,如果沒有模板引數串列的類模板的名稱出現在需要具體型別的背景關系中,它被稱為“推導型別別的占位符”,并且僅允許在[dcl.type.class.deduct]中列出的特定背景關系。最常見的一種是變數宣告,就像編譯器將在 C 17 及更高版本中std::pair p("foo", 1)推斷的那樣。std::pair<const char*, int>
在您的代碼中,您試圖參考類 template 的特定專業化Test,而不指定模板引數串列,而不是在可以推斷模板引數的背景關系中。因此,這是不允許的。
uj5u.com熱心網友回復:
新的類模板引數推導 (CTAD)(C 17 起)應用于宣告。運算式foo<Test<>>(t);不是宣告,它是模板函式呼叫。
uj5u.com熱心網友回復:
在您的第一個代碼片段中,您將類模板 ( Test) 指定為模板引數,foo而不是型別(如類模板的實體)。您需要一個帶有模板模板引數的函式來處理它。
例子:
#include <type_traits>
template<template<class> class T, class U> // T = Test, U = deduced to int
void foo(T<U>& bar) {
std::cout << std::is_same<T<U>, Test<int>>::value << '\n'; // true
}
int main() {
Test t;
foo<Test>(t); // now ok
}
在您的第二個片段中,foo<Test<>>(t);instantiates foo<Test<int>>(Test<int>&);since<>使模板實體化使用模板引數的默認型別,即int.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/452863.html
上一篇:為什么這個部分模板專業化失敗了?
