冲突的不匹配标签使用标准库进行编译,但不能编译

时间:2017-08-06 19:27:43

标签: c++ c++11 templates tuples

我正在研究如何在我的系统上的标准库中定义std::tuple_size。我有一台Mac OS,编译器版本为Apple LLVM version 8.1.0 (clang-802.0.42)。标准库位于InstalledDir

输出的g++ --version位置

鉴于以下代码无法编译(因为clang不喜欢将某些内容专门化/重新声明为struct,之前已定义为class,反之亦然)< / p>

#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 :(得分:2)

  

鉴于以下代码无法编译(因为clang不喜欢将某些内容专门化/重新声明为以前定义为类的结构,反之亦然)

clang很好。

  

出现以下错误

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

这表明a)您启用了默认情况下未启用的警告,即-Wmismatched-tags,以及b)您请求将警告视为错误。

此警告存在是为了与其他编译器兼容。 C ++适用于不匹配的标签,因此所有符合标准的实现,所以是clang。除非你有充分的理由,否则你不应该启用此警告。

警告通常不会影响系统头,甚至是否会被视为错误的警告,这就是它在那里工作的原因,但是你自己的代码不是系统头,并且不是也不应该被授予相同的权限异常。

答案 1 :(得分: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”中的pragma行,并且应该编译没有问题。