簡體   English   中英

C ++模板:返回新類型的正確方法

[英]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...每個TiVtypes...相應的類型Vistd::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM