为nullptr提供模板推导的类型

时间:2015-10-01 09:11:14

标签: c++ templates nullptr

假设以下代码段:

template <class T>
void fct(T* a, T* b){
  // do something
}

A a;
fct(&a, nullptr); // Problem here!

这会带来麻烦,因为调用参数的类型为A*nullptr_t,因此编译器无法推导出模板参数T

一般来说,我可以想象如何解决这个问题:

  • 定义A* b = nullptr并使用fct(&a, b)
  • fct案例
  • nullptr定义一个带有一个参数的重载
  • 使用fct(&a, static_cast<A*>(nullptr))

还是有一个更干净的解决方案,比如创建类似&#34;输入的nullptr&#34;?

4 个答案:

答案 0 :(得分:6)

只需将第二个参数设为非推导的上下文,例如:

{{1}}

答案 1 :(得分:2)

我还建议采用以下解决方案:

template <class T, class U>
void fct(T* a, U b){
  T* b2 = b;
  // do something
}

A a;
fct(&a, nullptr); 

这允许更广泛地使用fct,但也许这正是你想要的。

例如,考虑

class A {};
class B : public A {};

...
A a;
B b;
fct(&a, &b); // calls fct<A>
// the following will not compile:
// fct(&b, &a);

答案 2 :(得分:1)

您可以使用以下代码:

#include <type_traits>

template<class T>
void f_impl(T*, T*)
{
    std::cout << typeid(T).name() << "\n";
}


template<class T, class U>
void f(T l, U r)
{
    static_assert((std::is_same<T, U>::value && std::is_pointer<T>::value) || 
                  (std::is_same<T, std::nullptr_t>::value && std::is_pointer<U>::value) || // First non-null 
                  (std::is_same<U, std::nullptr_t>::value && std::is_pointer<T>::value)    // Second non-null
                  , "");

    using P = typename std::conditional<std::is_same<T, std::nullptr_t>::value, U, T>::type; 

    f_impl<typename std::remove_pointer<P>::type>(l, r);
}

int main()
{
    int i;
    f(&i, nullptr);
    f(nullptr, &i);
    // f(i, nullptr); // won't compile - non-pointer
    f(&i, &i);

    double d;
    // f(&i, &d); // - won't compile

}

此版本测试允许使用一个f(但不是两个)调用nullptr,或者使用两个指向同一类型的指针。使用c ++ 14,您还可以使用std::conditional_tstd::remove_pointer_tstd::is_null_pointer之类的内容删除一些biolerplate。

答案 3 :(得分:0)

正如问题所述,std::nullptr_t实际上有一个类型:template <class T> void fct(T* a, std::nullptr_t b) { return fct<T>(a,static_cast<T*>(b)); } 。因此,只需为具体情况添加显式重载:

class U

不需要为此设置一些模板参数Option Explicit Sub Download_Outlook_Mail_To_Excel() Dim Folder As Outlook.MAPIFolder Dim sFolders As Outlook.MAPIFolder Dim iRow As Integer Dim oRow As Integer Dim MailBoxName As String Dim Pst_Folder_Name As String Const xlWorkbookName As String = "C:\Users\MacroMan\MyWorkbook.xlsx" '// change as required '// I'm using late binding in case you don't actually have a reference set. Dim xlApp As Object Dim xlWB As Object Set xlApp = CreateObject("Excel.Application") xlApp.Visible = False Set xlWB = xlApp.Workbooks.Open(xlWorkbookName) MailBoxName = "Backupmailbox" Pst_Folder_Name = "Inbox1" 'Sample "Inbox" or "Sent Items" 'To directly a Folder at a high level 'Set Folder = Outlook.Session.Folders(MailBoxName).Folders(Pst_Folder_Name) 'To access a main folder or a subfolder (level-1) For Each Folder In Outlook.Session.Folders(MailBoxName).Folders If VBA.UCase(Folder.Name) = VBA.UCase(Pst_Folder_Name) Then GoTo Label_Folder_Found For Each sFolders In Folder.Folders If VBA.UCase(sFolders.Name) = VBA.UCase(Pst_Folder_Name) Then Set Folder = sFolders GoTo Label_Folder_Found End If Next sFolders Next Folder Label_Folder_Found: If Folder.Name = "" Then MsgBox "Invalid Data in Input" GoTo End_Lbl1: End If 'Read Through each Mail and export the details to Excel for Email Archival xlWB.Sheets(1).Activate Folder.Items.Sort "Received" 'Insert Column Headers xlWB.Sheets(1).Cells(1, 1) = "Sender" xlWB.Sheets(1).Cells(1, 2) = "Subject" xlWB.Sheets(1).Cells(1, 3) = "Date" xlWB.Sheets(1).Cells(1, 4) = "Size" xlWB.Sheets(1).Cells(1, 5) = "EmailID" 'ThisWorkbook.Sheets(1).Cells(1, 6) = "Body" 'Export eMail Data from PST Folder oRow = 1 For iRow = 1 To Folder.Items.Count 'If condition to import mails received in last 60 days 'To import all emails, comment or remove this IF condition If VBA.DateValue(VBA.Now) - VBA.DateValue(Folder.Items.Item(iRow).ReceivedTime) <= 60 Then oRow = oRow + 1 xlWB.Sheets(1).Cells(oRow, 1).Select xlWB.Sheets(1).Cells(oRow, 1) = Folder.Items.Item(iRow).SenderName xlWB.Sheets(1).Cells(oRow, 2) = Folder.Items.Item(iRow).Subject xlWB.Sheets(1).Cells(oRow, 3) = Folder.Items.Item(iRow).ReceivedTime xlWB.Sheets(1).Cells(oRow, 4) = Folder.Items.Item(iRow).Size xlWB.Sheets(1).Cells(oRow, 5) = Folder.Items.Item(iRow).SenderEmailAddress 'ThisWorkbook.Sheets(1).Cells(oRow, 6) = Folder.Items.Item(iRow).Body End If Next iRow MsgBox "Outlook Mails Extracted to Excel" Set Folder = Nothing Set sFolders = Nothing xlWB.Close False Set xlWB = Nothing xlApp.Quit Set xlApp = Nothing End_Lbl1: End Sub