問題描述
在回答這個問題時,關于嘗試構造一個可變參數轉發引用構造函數,只有在沒有其他構造函數時才應調用該構造函數有效的.也就是說,如果有:
In answering this question about trying to construct a variadic forwarding reference constructor that should only be called if no other constructor is valid. That is, if there was a:
C(const char*, size_t) { } // 1
template <typename... T, ???> C(T&&... ) { } // 2
我們希望 C c1{"abc", 2};
調用 (1),盡管需要轉換,但是 C c2{1, 2, 3};
調用 (2),因為 (1) 不適用.
We'd want C c1{"abc", 2};
to call (1), despite the required conversion, but C c2{1, 2, 3};
to call (2), as (1) cannot apply.
我提出了以下解決方案:
I proposed the following solution:
template <typename... T,
typename = std::enable_if_t<!std::is_constructible<C, T&&...>::value>
>
C(T&&... ) { }
我的意思是說,我嘗試過并驚訝地發現它確實有效.它編譯并完成了我對 gcc 和 clang 的期望.但是,我無法解釋為什么它起作用,或者即使它實際上應該起作用,而且 gcc 和 clang 都特別包容.是嗎?為什么?
And by proposed, I mean, I tried it and was surprised to discover that it actually works. It compiles and does exactly what I had hoped for on both gcc and clang. However, I am at a loss to explain why it works or even if it's actually supposed to work and gcc and clang are both just being particularly accommodating. Is it? Why?
推薦答案
你的代碼的問題是我們只是在一個上下文中實例化了 is_constructible
,它得到了錯誤的答案.模板代碼中的任何類型的緩存都可能導致錯誤——嘗試在調用構造函數后在相同的參數上打印 is_constructible
!很可能會弄錯.
The issue with your code is that we just instantiated is_constructible
in a context where it gets the answer wrong. Any kind of caching in the template code is likely to result in bugs -- try printing is_constructible
on the same parameters after you call the constructor! It is likely to get it wrong.
現場示例,說明如何出錯.請注意,它聲稱 C
不能從 int&
構造,盡管在前一行已經這樣做了.
Live example of how it can go wrong. Notice it claims C
cannot be constructed from an int&
, despite having done so on the previous line.
struct C {
C(const char*, size_t) {}
template <class... Ts,
typename = std::enable_if_t<!std::is_constructible<C, Ts&&...>::value>
>
C(Ts&&... ) { }
};
int main() {
int a = 0;
C x{a};
std::cout << std::is_constructible<C, int&>{} << '
';
}
糟糕.
我懷疑這可能是 ODR 違規——is_constructible
的兩個定義在不同的位置有不同的類型?或者也許不是.
I suspect this might be an ODR violation -- the two definitions of is_constructible
have different types at different spots? Or maybe not.
沒有這個問題的原始問題的解決方案也貼出來了.
這篇關于后備可變參數構造函數 - 為什么這有效?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!