gcc和clang之间的C ++不一致 [英] C++ inconsistency between gcc and clang

查看:577
本文介绍了gcc和clang之间的C ++不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了 gcc (版本 4.8.1 4.8)之间的C ++不一致.2 )和 clang (版本 3.3 / code>)。我不知道哪一个是正确的。以下是程序:

I came across a C++ inconsistency between gcc (versions 4.8.1, 4.8.2) and clang (versions 3.3, 3.4). I wonder which one is correct. Here's the program:

template < typename T > struct Result {};
template < typename T > struct Empty {};

template < typename T >
struct Bad_Type_Fcn {
    typedef typename Empty< T >::type type;
};

template < typename T >
Result< T >
f( const T& ) {
    return Result< T >();
}

template< class U >
Result< typename Bad_Type_Fcn< U >::type >
f( const U&, int ) {
    return Result< typename Bad_Type_Fcn< U >::type >();
}

int main() {
    (void)f< int >(42);
}

很明显,这段代码并不意味着什么;它是对Boost Range库中出现的东西的一个积极的简化( f 简化 make_iterator_range )。 Bad_Type_Fcn 是一个类型函数(技术上, struct ),不应该实例化,因为 Empty< T> :: type 从不存在,对于任何 T 。此 struct f()的第二个模板特化的存在本身不是一个错误。 IRL, f() Bad_Type_Fcn 不为空的某些类型提供了一些功能。然而这不是这里的关注,这就是为什么我简化了这些。我仍然希望 f()适用于 Bad_Type_Fcn 为空的类型。

Clearly, this code is not meant to do anything; it is an aggressive simplification of something that appears in the Boost Range library (with f simplifying make_iterator_range). The Bad_Type_Fcn is a type function (technically, a struct) which should never be instantiated, because Empty<T>::type never exists, for any T. The presence of this struct and of the second template specialization of f() is not an error in itself. IRL, f() provides some functionality for certain types for which Bad_Type_Fcn is not empty. However that is not the concern here, which is why I simplified those out. I still want f() to work for types where Bad_Type_Fcn is empty.

我使用 {g ++ | clang ++} [-std = c ++ 0x] -pedantic -Wall -Wextra -c 进行编译。语言标准选择似乎没有影响。使用 clang ,程序编译时没有错误或警告。使用 gcc 时,会出现错误:

I'm compiling with {g++|clang++} [-std=c++0x] -pedantic -Wall -Wextra -c. The language standard selection doesn't seem to make a difference. With clang, the program compiles without errors or warnings. With gcc, I get an error:

weird.cpp: In instantiation of ‘struct Bad_Type_Fcn<int>’:
weird.cpp:17:5:   required by substitution of ‘template<class U> Result<typename Bad_Type_Fcn<T>::type> f(const U&, int) [with U = int]’
weird.cpp:22:26:   required from here
weird.cpp:6:43: error: no type named ‘type’ in ‘struct Empty<int>’
         typedef typename Empty< T >::type type;

似乎发生的是 clang 消除了 f()的第二个重载,可能是(?),因为调用只有一个参数,整数 42 ,而第二个重载需要2个参数。另一方面, gcc 不会消除第二个重载,而是尝试实例化 struct Bad_Type_Fcn

What seems to be happening is that clang eliminates the second overload of f(), probably(?) on the basis that the call is made with 1 argument only, integer 42, while the second overload requires 2 arguments. On the other hand, gcc doesn't eliminate the second overload, and instead tries to instantiate struct Bad_Type_Fcn<int>, which results in an error.

如果我在调用 f()时删除显式实例化,则不一致性消失,然后写(void)f(42);

The inconsistency disappears if I remove the explicit instantiation in the call to f(), and write (void)f(42); instead.

哪些编译器是正确的? / p>

Which of the compilers is correct?

推荐答案

我记得有关这个问题的WG21核心讨论,其中一个Clang开发人员援引14.7.1p7

I remember a WG21 core discussion about this, and one of the Clang developers defended their position by citing 14.7.1p7


如果重载解析过程可以确定在不实例化类模板定义的情况下调用的正确函数,则未指定实例化是否实际发生。

If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.

另一方面,对于一个错误的程序(这是做必要的实例化时的情况)这样的正确的功能调用的概念,所以我同意在讨论的另一个人的位置,他说他不能看到这允许Cl走这条路线。

On the other hand, for an ill-formed program (which is the case here when doing the required instantiation), there is no such notion of "the correct function to call", so I agree to the position of another guy in that discussion who said that he can't see that this allows Clang to go that route.

在p7的例子中,它显示的代码是良好的形式,有和没有做额外的实例化。

In the example of p7 it shows code that is well-formed both with and without doing the additional instantiation.

em>,即使Clang被允许这样做,你的程序的良好形式将依赖于特定的事件(未指定的行为)。因此,标准不再需要你的程序被接受,诚实地,我不知道这是什么意思。我认为这样的代码是不成形的。

In any case, even if Clang is allowed to do it, the well-formedness of your program would then rely on particular happenstances (unspecified behavior). The Standard therefore doesn't anymore require your program to be accepted, and honestly I don't know what that means. I regard such code as being ill-formed.

这篇关于gcc和clang之间的C ++不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆