[英]C++ Templates: correct way to return a new type
抱歉通用標題,但我無法集中解決問題。
我有一個模板化的類方法接受一個參數包並提供一個新的類型作為回報,以隱藏實現的細節。 更具體地說,該類處理SQLite查詢,並且該方法在執行查詢之前調用sqlite3_prepare()
來准備語句。
class Table {
...
template <typename ...Ts>
class PreparedStatement { ... };
template <typename ...Ts>
PreparedStatement<Ts...> prepare(std::tuple<Ts...> tuple) {
// do something
return PreparedStatement<Ts...> ( ... );
}
這適用於“普通”類型,但是當參數聲明為const
時會出現問題:
const Field<int> fld = createField<int>("name");
...
PreparedStatement<decltype(fld)> s = prepare(make_tuple(fld));
錯誤如下:
no match for 'operator =' (operand types are PreparedStatenent<const Field<int>> and PreparedStatement<Field<int>>
我懷疑問題出在我的函數聲明中,有沒有辦法解決這個問題並使函數更“優雅”?
注意 :我知道我可以通過手動聲明s
變量來解決問題,但我懷疑的是如何實現該方法。
正如許多人問的那樣,這是一個例子:
#include <tuple>
template <typename T>
struct Field {
};
class Table {
public:
template <typename ...Ts>
class PreparedStatement {
public:
PreparedStatement() {};
};
template <typename ...Ts>
PreparedStatement<Ts...> prepare(std::tuple<Ts...> tuple) {
// do something
return PreparedStatement<Ts...> ( );
}
};
int main()
{
Field<int> fld;
Table t;
Table::PreparedStatement<decltype(fld)> p;
p = t.prepare(std::make_tuple(fld));
// here comes the problem
const Field<int> f2;
Table::PreparedStatement<decltype(f2)> p2;
p2 = t.prepare(std::make_tuple(f2));
return 0;
}
這是編譯器輸出
main.cpp:在函數'int main()'中:main.cpp:35:39:錯誤:'operator ='不匹配(操作數類型是'Table :: PreparedStatement>'和'Table :: PreparedStatement>') p2 = t.prepare(std :: make_tuple(f2)); ^ main.cpp:10:10:注意:候選:constexpr Table :: PreparedStatement>&Table :: PreparedStatement> :: operator =(const Table :: PreparedStatement>&)class PreparedStatement {^ ~~~~~~~~ ~~~~~~~~ main.cpp:10:10:注意:參數1從'Table :: PreparedStatement>'轉換為'const Table :: PreparedStatement>&'main.cpp:10:10:注意:候選人:constexpr表:: PreparedStatement>&Table :: PreparedStatement
:: operator =(Table :: PreparedStatement> &&)main.cpp:10:10:注意:參數1從'Table :: PreparedStatement>'到'Table :: PreparedStatement> &&'沒有已知的轉換
更新正如許多人所指出的,我可以使用auto
來推斷出類型,但在某些情況下, auto
幾乎不能使用。 例如,一個是我需要在類上下文中聲明語句。 所以假設出於某種原因禁止使用auto
。 沒有任何其他解決方案可用嗎? 請參閱上面的更新代碼。
cppreference.com for make_tuple告訴我們:
template< class... Types > tuple<VTypes...> make_tuple( Types&&... args );
對於
Types...
每個Ti
,Vtypes...
相應的類型Vi
是std::decay<Ti>::type
除非應用std::decay
導致某些類型X
std::reference_wrapper<X>
,在這種情況下,推導出的類型是X&
。
而std::decay
除其他外,還刪除了cv-qualifiers。 所以你的類型不是PreparedStatement<const Field<int>>
,而是PreparedStatement<Field<int>>
。
您可以像manni66一樣使用auto
來避免此類問題。
auto s = prepare(make_tuple(fld));
我可以使用auto來推斷類型,但在某些情況下auto實際上不能使用。 例如,一個是我需要在類上下文中聲明語句。 所以假設出於某種原因禁止使用auto。 沒有任何其他解決方案可用嗎? 請參閱上面的更新代碼。
您可以使用decltype
表達式來計算prepare
返回的值,而不是auto
。
我的意思是......而不是
Table::PreparedStatement<decltype(f2)> p2;
你可以試試
decltype(t.prepare(std::make_tuple(f2))) p2;
要么
decltype(std::declval<Table>().prepare(
std::make_tuple(std::declval<Field<int>>()))) p2;
我想你也可以使用類似的decltype()
來聲明你的類的成員。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.