2011-07-28 67 views
9

在編譯時使用宏和標記串聯在寬字符串和窄字符串之間切換是很常見的。通過串聯創建原始字符串時是否還原了trigraph替換?

#define _T(x) L##x 
const wchar_t *wide1 = _T("hello"); 
const wchar_t *wide2 = L"hello"; 

而在C++ 11應該是有效炮製與原始字符串類似的事情:

#define RAW(x) R##x 
const char *raw1 = RAW("(Hello)"); 
const char *raw2 = R"(Hello)"; 

由於轉義序列取代前宏擴展和令牌級聯發生,這應該防止轉義序列在引用的字符串中被替換。

但是這怎麼適用於trigraphs?通過與正常字符串串聯形成的原始字符串是否仍然受到其三字母替換的回覆?

const char *trigraph = RAW("(??=)");  // Is this "#" or "??="? 
+2

在編譯器中試用這個程序需要多長時間,而不是在這裏問問題的時間? –

+5

我不想在生產代碼中使用它,我正在編寫一個編譯器,它看起來像是一個邊緣案例。此外,我不知道任何具有完整C++ 0x支持的編譯器(並且我不認爲最終的標準甚至已經發布)。 –

+7

@Damien這不是一個合適的答案......我知道C++編譯器會偏離規範 –

回答

6

不,在您的示例中不會恢復trigraph。

[lex.phases]p1標識翻譯的三個階段有關你的問題:

1.三字符序列通過相應的單個字符的內部表示替換。
3.源文件被分解爲預處理標記。
4.宏調用已擴展。

階段1由[lex.trigraph]p1定義。在此階段,您的代碼被翻譯爲const char *trigraph = RAW("(#)")

階段3由[lex.pptoken]定義。這是trigraphs在原始字符串文字中被還原的階段。第3段表示:

如果下一個字符開始的字符序列可能是預連接x和原始字符串文字,如R」的初始雙引號,下預處理標記應是原始字符串文字。原始字符串的初始和網絡最終在雙引號字符,在階段1和2(三字母,通用字符,名稱和行拼接)進行任何變革都還原。

不在的情況下你例如,因此trigraph不會被還原。代碼變換成預處理令牌序列constchar*trigraph=RAW("(#)")

最後,在階段4中,RAW宏展開併發生令牌糊,導致以下順序預處理 - 令牌constchar*trigraph=R"(#)"。字符串文字的r-字符序列包括#。階段3已經發生,並且沒有其他發生三撇子逆轉的點。

0

Trigraph替換髮生在宏處理之前。

UPD請忽略此操作。我還沒有意識到,C++ 0x恢復原始字符串文字中的三字母。

UPD2 2.5.3描述了形成原始字符串文字預處理標記的過程。 Trigraph逆轉是這個過程的一部分。沒有沒有預處理令牌的原始字符串。所以你的問題的答案似乎是肯定的。

+1

據我所知,替換髮生在宏處理之前,但是標準是指trigraph替換/原始字符串文字。由於原始字符串文字只是稍後形成(作爲串聯的結果),所以我很好奇這是否仍然如此。 –

相關問題