我正在通過這個特定的 SO來了解如何為自定義洗掉器指標節省記憶體空間。在答案的底部,它提供了一個用 C 11 撰寫的自定義版本。
在嘗試理解代碼的幾十分鐘之后,我發現 Big 3 之間存在一些編譯器不一致,其中 clang 編譯,而另外兩個則抱怨編譯器錯誤。(現場演示)
我的代碼與其他 SO 答案略有不同。它是這樣的:
#include <cstdlib>
#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;
template <class T, T t>
struct val {
constexpr operator typename decay<T>::type() const noexcept {
return t;
}
};
using default_free = val<decltype(free), free>;
int main(void) {
unique_ptr<void, default_free> p(malloc(42));
cout << p.get() << endl;
p.reset();
cout << p.get() << endl;
return 0;
}
如果我在這里錯了,請糾正我。在我看來,訣竅是提供一個 constexpr 函式,該函式可以將型別物件轉換為default_delete具有t(free作為其實體化)值的函式指標。
所以問題是:哪個編譯器是正確的?
uj5u.com熱心網友回復:
它似乎是一個 gcc 錯誤,和一個完全不同的 MSVC 錯誤。
gcc 不能這樣做:
template <typename T, T t> struct foo {};
當使用函式型別實體化時。T必須是觸發此錯誤的模板引數;template <void t(void*) noexcept>作品。
template <typename T, T* t> struct foo {};
解決問題。
MSVC 很好地處理了前面的任何一種構造,但它不能free用作非型別模板引數。(其他標準C庫函式也是如此。)一種簡單的解決方案是使用一個合格的名稱(或者::free或std::free,兩者的作業)。包裝free在另一個函式中也可以解決這個問題。這是因為 MSVC 顯然認為(在這種情況下)::free和std::free是不同的功能,無法消除歧義。可以在沒有標準庫的情況下重現這一點:
void foo(void*);
namespace moo {
using ::foo;
}
using namespace moo;
現在,plainfoo不能用作模板引數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/312591.html
下一篇:創建C 物件的模板類的新實體
