模板化转换运算符类型推导在clang和gcc中有所不同

时间:2016-05-02 17:36:30

标签: c++ templates gcc clang++ type-deduction

过去几天我一直在努力解决编译器之间关于模板化转换运算符类型推导的差异,并且我最终将至少一个差异归结为堆栈溢出大小的示例:

final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    if(passwordEncoder.matches(rawPassword, encodedPassword)){
        return true;
    else{
       return false;
       }

Demo

表达式void foo(int i); struct any_const_reference { template <typename T> operator const T&(); }; template <typename T, typename Enable=void> struct detect_call : std::false_type { }; template <typename T> struct detect_call<T, decltype( declval<T>()( any_const_reference() ) ) > : std::true_type { }; 在clang中提供detect_call<decltype(foo)>::value,在gcc中提供true(使用我可以获得的任何编译器的任何现代版本,最新的是gcc 5.2和clang 3.8 )。问题:

  • 哪个是对的?那是符合C ++标准的吗?
  • 造成这种差异的原因是什么?
  • 一般情况下,转换运算符(或此表单的任何转换运算符,例如false)中应用于T的类型推导规则是什么,以及它们在C ++标准?

注意:这似乎与这个问题类似:Template argument type deduction by conversion operator(事实上,我也遇到了这个确切的差异),但我还没有看到答案之间的映射和这个案子。如果这只是此问题的另一个实例,那么这个问题归结为如何将该问题映射到此用例。

1 个答案:

答案 0 :(得分:4)

这可以简化为实际调用foo()

void foo(int ) { }

struct any_const_reference {
  template <typename T>
  operator const T&();
};

int main() {
    foo(any_const_reference{}); // ok on clang
                                // error on gcc
}

这是一个gcc错误(上面根据TC的评论#63217)。根据{{​​3}},这应该将T推断为int,因为应删除引用和限定符(在这种情况下,Pconst T&和{{1} }是A)。