この場合、正規表現は不要なオーバーヘッドです。このジョブを実行するには、 1 文字std::string::findで十分です。各パラメーター (最初のパラメーターも) で始まると仮定すると#、値はオプション (デフォルトは"") であり、末尾#は常に省略されます。次のように実行できます。
std::string pstr = ...; // the parameter string
typedef std::pair<std::string, std::string> Param;
std::vector<Param> params;
std::size_t pos = pstr.find('#');
std::size_t next = pstr.find('#', pos);
while (pos != std::string::npos) {
    std::string param, value;
    std::size_t sep_pos = pstr.find('~', next);
    if (sep_pos != std::string::npos) {
        value = pstr.substr(sep_pos + 1, next - sep_pos - 1);
        param = pstr.substr(pos + 1, sep_pos - pos - 1);
    } else {
        param = pstr.substr(pos + 1, next - pos - 1);
    }
    params.push_back(Param(param, value));
}
注意してください、それstd::strtokは悪い提案です。この関数は安全ではないため、通常の C++ コードでは使用しないでください。