2017-08-06 16 views
4

我正在看看std::tuple_size是如何在我的系統上的標準庫中定義的。我有一個Mac OS,編譯器版本是Apple LLVM version 8.1.0 (clang-802.0.42)。標準庫在InstalledDir位置發現g++ --version衝突的不匹配標籤使用標準庫進行編譯,但不是其他方式

作爲輸出鑑於下面的代碼不編譯(因爲clang不喜歡專門/重新聲明的東西如先前定義爲class,反之亦然struct

#include <iostream> 
#include <utility> 
#include <array> 
#include <tuple> 
#include <type_traits> 

using std::cout; 
using std::endl; 

template <class T> 
class Something; 
template <class One, class Two> 
struct Something<std::pair<One, Two>>; 
template <class One, class Two> 
class Something<std::pair<One, Two>> 
    : public std::integral_constant<int, 2> {}; 

int main() { 
    cout << std::tuple_size<std::array<int, 2>>::value << endl; 
    cout << std::tuple_size<std::tuple<int, int>>::value << endl; 
    cout << std::tuple_size<std::pair<int, int>>::value << endl; 
} 

,出現以下錯誤

error: struct template 'Something' was previously declared as a class template [-Werror,-Wmismatched-tags] 
struct Something<std::pair<One, Two>>; 
^ 
test.cpp:49:7: note: previous use is here 
class Something; 

我看到了下面的代碼在標準庫的頭<array>(與tuple_size按照後面的專門定義爲class

template <class T> class tuple_size; 
template <size_t I, class T> class tuple_element; 
template <class T1, class T2> struct tuple_size<pair<T1, T2> >; 

如何消除對Something的定義和聲明後,在上面的代碼中使用時這個編譯?上述代碼是否應該提出關於tuple_size被定義或聲明兩次的警告,作爲class和另一個作爲struct

+2

也許這將是很好的添加您的問題的上下文。我今天看到你以前的問題(你可能已經刪除了,因爲我現在看不到它們)並且發現當前的問題是合法的。然而,如果沒有這種背景,這個問題可能會被認爲是一種不完整的... –

+0

@ W.F。我刪除了他們,因爲我不想進入解釋我自己的論點。人們似乎並不喜歡上下文,並認爲它超出了範圍。我無法複製我的工作基礎架構的環境,所以我已經縮小了我認爲在那裏的標準庫以及我不瞭解的問題的範圍。 – Curious

+0

好吧,稍微強調結構/類問題可以使問題更清楚一些,我認爲... –

回答

0

我想大公<array>編譯感謝

#pragma GCC system_header 

,你可以在那裏找到(或者,至少,在我的版本的頭的)。

試着寫了下面的頭( 「something.h」)

#ifndef _something_h_ 
#define _something_h_ 

//#pragma GCC system_header 

template <class T> 
class Something; 

template <class One, class Two> 
struct Something<std::pair<One, Two>>; 

template <class One, class Two> 
class Something<std::pair<One, Two>> 
{}; 

#endif /* ndef _something_h_ */ 

和修改主CPP文件如下

#include <iostream> 
#include <utility> 
#include <array> 
#include <tuple> 
#include <type_traits> 

#include "something.h" 

using std::cout; 
using std::endl; 

int main() { 
    cout << std::tuple_size<std::array<int, 2>>::value << endl; 
    cout << std::tuple_size<std::tuple<int, int>>::value << endl; 
    cout << std::tuple_size<std::pair<int, int>>::value << endl; 
} 

在pragma行註釋,你應該得到同樣的錯誤。

取消註釋「something.h」中的編譯指示行,並且應該編譯時沒有問題。

2

鑑於下面的代碼不編譯(因爲鐺不喜歡專門/重新聲明的東西如先前定義爲類和反之亦然結構)

鐺是細跟那。

,出現以下錯誤

error: struct template 'Something' was previously declared as a class template [-Werror,-Wmismatched-tags] 

這表明a)您啓用了默認情況下不,即-Wmismatched-tags啓用警告,和b)您的要求將警告視爲錯誤。

此警告存在與其他編譯器的兼容性。 C++可以處理不匹配的標籤,因此所有符合的實現都是如此,clang也是如此。除非你有很好的理由,否則你不應該啓用這個警告。

警告通常不會影響系統頭文件,甚至警告,否則會被視爲錯誤,這就是爲什麼它在那裏工作,但你自己的代碼不是系統頭,並且不應該被授予同樣的例外。

+0

好吧,讓我們假設系統標題本身不會引起問題,因爲它被標記爲特殊的東西。但那麼客戶端代碼會發生什麼?即使系統頭文件包含雙聲明,該如何編譯?編譯器是否仍然照顧它? – Curious

+0

'C++很好,不匹配的標籤',你能給出一個標準或cppreference的報價去呢? – Curious

+0

@Crary對不起,但我不認爲這是公平的。當你認爲它告訴你這是無效的時候,你信任你的編譯器,我給了足夠的細節讓你的編譯器告訴你它實際上是有效的。無論如何,該標準覆蓋了[dcl.type.elab] p3。 – hvd

相關問題