我有一個模板化的類,但只能從建構式推匯出模板引數的一部分。
有沒有辦法在呼叫建構式時在尖括號內提供其余的模板引數?
假設我們使用的是 C 17。
template<typename T1, typename T2>
struct S
{
T2 t2;
S(const T2& _t2) : t2{_t2} {}
void operator()(const T1& t1)
{
std::cout << t1 << ", " << t2 << '\n';
}
};
int main()
{
S<int, double> s {3.14};
std::function<void(int)> func = s;
func(42);
// What I want:
//S<int> s2 {3.14}; <- T1 is provided in the angle brackets, T2 is deduced
//std::function<void(int)> func2 = s;
//func2(42);
}
據我所知,我們需要在尖括號中提供所有模板引數,或者不提供所有模板引數并使用 CTAD。問題是我不想寫所有的模板引數(在我的實際用例中大約有 5-6 個,而且它們非常冗長)但我也不想在建構式中傳遞所有引數,因為其中一些不用于構造物件。我只需要它們的 operator() 方法型別。
我無法使 operator() 方法模板化,因為我想將它系結到 std::function 物件,并且我無法在系結期間推斷模板引數型別。所以這就是為什么我需要包裝類中的所有型別。
這種部分模板推導存在于函式中。
例如:
template<typename T1, typename T2>
void foo(const T2& t2)
{
T1 t1{};
std::cout << t1 << ", " << t2 << '\n';
}
int main()
{
foo<int>(3.4); //T1 is explicitly int, T2 is deduced to be double
}
我目前的解決方案是利用這個特性,通過一個函式構造物件:
template<typename U1, typename U2>
S<U1, U2> construct_S(const U2& t2)
{
return S<U1, U2>{t2};
}
int main()
{
auto s2 = construct_S<int>(1.5);
std::function<void(int)> func2 = s2;
func2(23);
}
我發現這個解決方案很笨拙,因為我們使用外部函式來構造物件。
我想知道是否有更清潔的解決方案來執行此操作。
也許有演繹指南的東西?我不知道。
uj5u.com熱心網友回復:
如評論中所述,您可以使用嵌套類,以便可以單獨提供兩個引數(一個顯式地推匯出另一個):
template<typename T1>
struct S {
template <typename T2>
struct impl {
T2 t2;
impl(const T2& _t2) : t2{_t2} {}
};
template <typename T2>
impl(const T2&) -> impl<T2>;
};
int main() {
S<int>::impl<double> s {3.14};
S<int>::impl s2 {3.14}; // <- T1 is provided in the angle brackets, T2 is deduced
}
我發現了這個如何為嵌套模板類提供演繹指南?. 盡管如此,上面的代碼編譯時 gcc 和 clang 都沒有問題:https : //godbolt.org/z/MMaPYGbe1。
如果重構類模板不是一種選擇,則輔助函式是一種常見且干凈的解決方案。標準庫有很多make_xxx功能,其中一些功能是在 CTAD 出現之前才需要的。
uj5u.com熱心網友回復:
最簡單的方法是提供工廠函式來接管型別的推導:
template<typename T1, typename T2>
auto makeS(T2 x) -> S<T1, T2>
{
return S<T1, T2>{x};
}
https://godbolt.org/z/4cPTdv7e3
uj5u.com熱心網友回復:
template<typename T2>
struct S
{
T2 t2;
S(const T2& _t2) : t2{_t2} {}
template<typename T1>
void operator()(const T1& t1)
{
std::cout << t1 << ", " << t2 << '\n';
}
};
int main()
{
S s {3.14}; // T1 not provided
std::function<void(int)> func2 = s; // T1 deduced by std function
func2(42); // works
}
我剛剛洗掉T1并將其作為模板引數,operator()一切正常。
活生生的例子。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/376719.html
下一篇:方法的輸入取決于模板結構
