C++17 更通用的 union:variant

std::variantC++17 中,一個新加入標準函式庫的 template 容器;他的概念基本上是和 union參考)一樣,是一個可以用來儲存多種型別資料的容器。

比如說:

std::variant<int, double> v;

就代表 v 這個變數,可以用來儲存 intdouble 的資料,variant 內部自己會去記錄相關的資訊。

而和 union 不同的地方,variant 也是 type-safe 的,再加上有許多函式可以搭配使用,所以在使用上應該算是相對安全;另外也由於他是標準函式庫的 template class,在使用時不需要另外去宣告一個新的型別。

閱讀全文

廣告

使用 gcc 建置 Boost 時開啟 c++11 的功能

Heresy 在 2010 年開始使用 Boost C++ Libraries(官網)的時候,已經有寫過一篇《Boost C++ Libraries 簡介》,大致介紹過這套半 C++ 官方的函式庫集合,以及他的建置方法了。

而之後,其實也有寫了不少文章,來介紹裡面的一些函式庫(參考)。

至於這一篇呢,則是簡單紀錄一下,在 Linux 環境下如果想要自行建置 Boost 的話,要怎麼開啟 c++11 的支援。

閱讀全文

Ubuntu 16 遇到的 g++ 5.x ABI 不相容問題

Heresy 目前開發跨平台的 C++ 程式的時候,主要是透過 Windows 10 的「Bash on Ubuntu on Windows」這個 Windows Subsystem for Linux(WSL)來進行操作的。

在微軟剛貼出的時候,他的 Ubunutu 版本還是 14,而後來在微軟推出 Creators Update (1703) 的時候,也把 Ubuntu 的版本升級到 16.04 了~而在 Ubuntu 系統版本升級的同時,系統預設使用的編譯器也由 g++ 4.x 更新到 g++ 5.x 了。

而也因為這樣,當 Heresy 要做 Linux 環境的建置測試的時候,也碰到了一些問題,這邊就稍微紀錄一下了。

首先,會有問題的主要原因,是 GCC5.1 在發布的同時,也推出了新的 libstdc++;而這個 C++ 的標準函式庫為了符合 C++11 的標準,重新實作了 std::stringstd::list;而這兩個類別由於遵循了新的規範(禁止 Copy-On-Write),所以變得和舊版的函式庫不相容。

為了避免混亂,gcc 5.1 修改了對應的 ABI(Application binary interface),像是 std::list<int> 實際上會是定義成 std::__cxx11::list<int> 的形式;基本上,就是有部分標準函式庫的東西的 namespace 會從 std 變成 std::__cxx11 了。

閱讀全文

支援科學記號的 QSpinBox

Qt 本身有提供 QDoubleSpinBox 這個元件(官網),可以提供使用者來輸入浮點數(小數),不過他基本上並不支援「科學記號」(科學記數法、Scientific notation、維基百科),所以如果要輸入極大的數字、或是相當接近 0 的小數時,都會相當麻煩。

查了一下,Qt 似乎沒有特別針對科學記號設計類似的元件,所以如果有這樣的需求,就得自己來了。

針對這個問題,網路上可以找到一些討論,也有一些實作,但是看起來好像都很複雜?

後來 Heresy 自己玩了一下,發現其實只要繼承 QDoubleSpinBox 並搭配 QDoubleValidator官網)的話,其實可以相對簡單地建立出一個支援科學記號的版本。

下面這個 QScientificSpinBox,就是一個簡單的實作:

閱讀全文

自行使用 VisualStudio 建置 QtAV

之前在《使用 Qt 撰寫影片播放程式的一些紀錄》一文,Heresy 有大概紀錄一下使用 Qt 5.x 內建的 QMediaPlayer 來撥放影片的方法;不過當時也碰到了一些問題,所以 Heresy 後來也有試著找一些替代方案來用。

後來是發現 QtAV 這個整合了 Qt 和 FFmpeg(官網)的這個專案似乎還算不錯,所以就認真研究看看了。

QtAV 的官方網站是:http://www.qtav.org/,原始碼則是在 https://github.com/wang-bin/QtAVhttps://sourceforge.net/projects/qtav/

他基本上包含了 C++ 函式庫、對應的範例,以及兩個功能算是完整的播放軟體(C++ 與 QML)。

而由於他提供的預先編譯好的版本選擇有限,所以 Heresy 後來就開始研究怎麼自己編譯了。這篇基本上就是怎麼在 Windows 環境下,使用 Visual C++ 來進行建置的紀錄:

閱讀全文

QWizard 傳遞自訂變數

之前有大概介紹過一下使用 Qt 的 QWizard 的使用經驗了。

而當時也有提到,在不同的 QWizardPage 之間,要交換資料的話,基本上是要靠「field」的機制來進行的,這部分的說明主要是官方的《Registering and Using Fields》這份文件(頁面)。

Qt 在這邊的設計,主要是靠 Qt 類別的預設「屬性」(property)、以及該屬性對應的存取子來做存取的。所以,當一個類別沒有指定預設要使用的屬性時,就需要透過 QWizardsetDefaultProperty() 這個函式(文件),來登記要使用的屬性名稱、以及對應的存取子。

像是之前也有提過,如果是以 QDoubleSpinBox 來說,如果想要在 QWizard 的架構下登記成 field 的話,就需要先執行下面的指令:

setDefaultProperty("QDoubleSpinBox", "value", "valueChanged");

他的第一個參數是類別的名稱,第二個參數則是要使用的屬性名稱(value),最後則是這個類別用來告知該屬性有變化的 signal(valueChanged)。

閱讀全文

使用 Parameter Pack 取代 switch 來做型別的展開

之前在寫《C++11 的「…」:Parameter Pack》的時候,有提過 Heresy 其實不太知道這東西該怎麼用?不過後來過了一小段時間,Heresy 倒是找到了一個可能的應用了!那就是用來

取代 switch case、拿來做型別的判斷、展開!

有的時候,在資料結構上可能會因為資料有不同的型別、而使用 template 來實作,然後再讓他去繼承一個抽象類別,來方便操作,例如下面就是一個例子:

class AbsData
{
public:
	virtual EType getType() const = 0;
};
 
template <typename TYPE>
class TData : public AbsData
{
public:
	TYPE mData;
 
	EType getType() const override;
};

在上面的程式碼中,AbsData 就是定義介面用的抽象類別,而 TData<> 則是可以對應各種型別的實作。

閱讀全文

C++14 編譯階段的整數序列的 integer_sequence

這篇雖然是在講 C++14 的「std::integer_sequence」(cppreference),不過實際上應該算是之前《C++11 的「…」:Parameter Pack》一文的延伸。

std::integer_sequence 是一個用來建立編譯階段(compile-time )的整數序列(不是陣列)的 template class,定義如下:

template< class T, T... Ints >
class integer_sequence;

而他是被定義在標準函式庫的 <utility> 這個標頭檔裡面,所以要使用的話,就需要引入這個檔案。

他最基本的使用方法大致上如下:

std::integer_sequence<int, 1, 3, 5, 7>()

這樣就代表了一個型別是 int 的序列、裡面有 1, 3, 5, 7 四個數值。

閱讀全文

C++11 的「…」:Parameter Pack

這篇文章,是當 Heresy 想研究「metaprogramming」(維基百科)的時候,看《Practical C++ Metaprogramming》這本書(O’Reilly)之後,跑去研究後的東西。

Parameter pack 是 C++11 在 template 這邊所新增的東西,主要分成「template parameter pack」和「function parameter pack」兩部分;他最明顯的特徵,就是程式碼裡面會多出一堆「…」了~ XD

這部分的文件,可以參考 cppreference,Heresy 這邊算是簡單紀錄、整理一下。

閱讀全文

C++14 到 C++17 的變化

這篇是參考《Changes between C++14 and C++17 DIS》,他主要是在描述 C++14 到 C++17 的變化;雖然由於 C++17 其實還是草案,所以很多東西都還有變數。不過由於他這邊整理的滿清楚的,所以這邊就稍微紀錄一下。

這篇文章,基本上把 C++14 到 C++17 的變化,整理出幾個部分:

  1. Removed or deprecated features(移除與已棄用的功能)
  2. New core language features with global / local applicability (新的核心語言功能)
  3. New library features(新的函式庫功能)
  4. Modifications to existing features(現有功能的修改)
  5. Miscellaneous(雜項)

閱讀全文