2017-06-02 89 views
8

考慮下面的代碼:推導引導和可變參數模板

#include <tuple> 
#include <iostream> 

template <class T> 
struct custom_wrapper 
{ 
    template <class Arg> 
    custom_wrapper(Arg arg): data(arg) {} 
    T data; 
}; 

template <class Arg> 
custom_wrapper(Arg arg) -> custom_wrapper<Arg>; 

template <class... T> 
struct custom_tuple 
{ 
    template <class... Args> 
    custom_tuple(Args... args): data(args...) {} 
    std::tuple<T...> data; 
}; 

template <class... Args> 
custom_tuple(Args... args) -> custom_tuple<Args...>; 

int main(int argc, char* argv[]) 
{ 
    custom_wrapper<int> w1(42); // OK 
    custom_wrapper w2(42);  // OK 
    custom_tuple<int> t1(42); // OK 
    custom_tuple t2(42);   // Fails 
    return 0; 
} 

失敗下克++ 7返回以下錯誤的行:

variadic_deduction_guide.cpp: In instantiation of 'custom_tuple<T>::custom_tuple(Args ...) [with Args = {int}; T = {}]': 
variadic_deduction_guide.cpp:31:23: required from here 
variadic_deduction_guide.cpp:19:45: error: no matching function for call to 'std::tuple<>::tuple(int&)' 
    custom_tuple(Args... args): data(args...) {} 

是正常或是編譯器故障?

回答

3

這是gcc bug 80871。接下來是解釋爲什麼代碼格式正確(並且在判定t2custom_tuple<int>時,clang是正確的)。


搞清楚做什麼用

custom_tuple t2(42); 

主要涉及合成一組函數,並對其進行重載決策過程。有關的候選人是從一個構造函數合成的功能和演繹指南:

template <class... T, class... Args> 
custom_tuple<T...> foo(Args...);  // the constructor 

template <class... Args> 
custom_tuple<Args...> foo(Args...); // the deduction guide 

從這一點來說它是一個基於你什麼是「尾隨參數包」是根據[temp.arg.explicit]/3演繹一個選擇自己的冒險:

未導出的尾隨模板參數包將被推斷爲模板參數的空序列。如果可以推導出所有的模板參數,則可以全部省略;在這種情況下,空模板參數列表<>本身也可以被省略。

T...沒有尾隨

這種情況很容易。我們只有一個可行的候選人(因爲T...不可扣除) - 扣除指南候選人。我們推斷Args...{int},所以我們以custom_tuple<int>結束。

T...拖尾

GCC和鐺其實也考慮扣除構造成功。所以,我們去的同分決賽中[over.match.best]

根據這些定義,一個可行的功能F1被定義爲比另一種可行的功能F2如果更好函數[...]

  • F1F2是功能模板專業化,並且根據[temp.func.order]中描述的部分排序規則,F1的功能模板比F2的模板更專門化,或者,如果不是那樣,
  • F1是從扣除指南([over.match.class.deduct])生成的,並且F2不是,或者如果不是,[...]

對於部分訂貨的目的,relevant types只是那些相應的功能參數,我們允許ignore unused template parameters,所以沒有函數模板被認爲比其他的更加專業化。

這讓我們更喜歡扣除指南,這是整個過程中最簡單的一步。我們推斷Args...{int},所以我們以custom_tuple<int>結束。


無論哪種方式,custom_tuple<int>是正確的決定。

+0

嗯,海灣合作委員會和鏗鏘樹幹不同意OP的代碼,我不是很確信這裏。首先是'T'「尾隨」? (這是一個相當不明確的術語。)其次,你能證明構造函數比扣除指南更專業嗎? –

+0

@ T.C。但很酷,看到克朗與扣除指南工作!這一定是相當新的。 – Barry

+0

這裏的上下文是一個函數調用,所以[「所使用的類型\ [對於偏序} \是那些函數調用具有參數的函數參數類型]](https://timsong-cpp.github.io/cppwp /temp.deduct.partial#3.1)。對於部分排序目的,[「一個模板參數可能保留沒有值,只要它不用於用於部分排序的類型」](https://timsong-cpp.github.io/cppwp/temp.deduct。部分#12),而'T ...'不是。那麼究竟如何比其他更專業?扣除失敗的方向如何? –