我想通過類型擦除(作爲簡單的格式化文本輸出庫的一部分)在包裝中包裝值類型。下面的函數print
應該採用封裝在類型擦除包裝器結構中的參數,該結構知道(通過函數指針)如何將其轉換爲字符串並進行打印。類型擦除工作或取決於優化級別失敗
它打印出0(或有時垃圾)當我編譯它:
g++ -std=c++11 -Wall -Wextra -O0 -o test test.cpp
但它工作時通過-O3
(-Og
也失敗)與-O1
編譯如預期。使用clang ++時,它的行爲相反(啓用優化時失敗)。我也試過g ++ -m32(我在我的x86_64 Linux Mint盒上有multilib gcc)和32位和64位mingw-w64交叉編譯器。行爲是相似的。此外,鏗鏘++ - libC++似乎總是失敗。
我必須觸發一些未定義的行爲(因爲我覺得g ++和clang ++不可能有相同的錯誤)。發生了什麼,我錯過了什麼?
#include <iostream>
#include <string>
using namespace std;
// Struct holding a pointer to a type-erased value and a function pointer to
// convert it to a string
struct TypeErasingWrapper {
void* item; // Pointer to type erased value
string (*to_string)(void*); // Function pointer to convert it to a string
};
// Convert any value pointer to a string (using the proper overload of
// std::to_string
template <typename T>
string toString (void* item)
{
return to_string(*reinterpret_cast<T*>(item));
}
// Wrap any value in a type-erasing wrapper
template <typename T>
TypeErasingWrapper wrap(T value) {
return {&value, toString<T>};
}
// Print a type erased value
void print(TypeErasingWrapper wrapper)
{
cout << wrapper.to_string(wrapper.item) << endl;
}
int main()
{
print(wrap(1234));
}
下面是沒有模板的版本,其行爲方式相同。
#include <iostream>
#include <string>
using namespace std;
// Struct holding a pointer to a type-erased int and a function pointer to
// convert it to a string
struct TypeErasingWrapper {
void* item; // Pointer to type erased int
string (*to_string)(void*); // Function pointer to convert it to a string
};
// Convert type-erased int to a string
string toString (void* item)
{
return to_string(*reinterpret_cast<int*>(item));
}
// Wrap an int in a type-erasing wrapper
TypeErasingWrapper wrap(int value) {
return {&value, toString};
}
// Print a type erased value
void print(TypeErasingWrapper wrapper)
{
cout << wrapper.to_string(wrapper.item) << endl;
}
int main()
{
print(wrap(1234));
}
嘎!不能相信我做到了。再次。謝謝你,先生!此外,我通常不會在文件範圍使用名稱空間標準(我想在此提供一個簡潔的版本),但感謝提示! – cyco130 2015-02-23 19:40:59