c++ - Clang 候选模板被忽略 : substitution failure (also fails to compile with gcc, VC 工作正常)

标签 c++ c++11 gcc clang clang++

我在使用 Clang 3.5 时遇到问题。以下是一个独立的重现。此代码使用 VC12 编译。使用 Clang 我收到以下错误:

1>C:\Users\jcuyle\code\branches\dev\ClientSDK\test\CompilerTestbed\CompilerTestbed.cpp(111,5): error : no matching function for call to 'out_from_storage'
1>          }( util::out_from_storage( rv ) );
1>             ^~~~~~~~~~~~~~~~~~~~~~
1>  C:\Users\jcuyle\code\branches\dev\ClientSDK\test\CompilerTestbed\CompilerTestbed.cpp(37,13):  note: candidate template ignored: substitution failure [with storage_t = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long, std::ratio<1, 1000000000> > > &]: no matching function for call to 'out_from_storage'
1>  inline auto out_from_storage( storage_t && storage ) -> decltype( util::details::template out_from_storage( std::forward< storage_t >( storage ) ) )
1>              ^                                                     ~~~~
1>  1 error generated.

代码如下:

#include <stdint.h>

#include <type_traits>
#include <chrono>
#include <utility>

namespace util
{
namespace details
{

template< typename RTy, typename Ty, typename enable = void >
inline RTy out_from_storage( Ty );

template< typename Ty, typename = typename std::enable_if< std::is_trivial< typename std::decay< Ty >::type >::value, Ty >::type >
inline typename std::add_pointer< typename std::decay< Ty >::type >::type out_from_storage( Ty&& t )
{
    return &t;
}

} // namespace details

template< typename storage_t >
inline auto out_from_storage( storage_t && storage ) -> decltype( util::details::out_from_storage( std::forward< storage_t >( storage ) ) )
{
    return util::details::out_from_storage( std::forward< storage_t >( storage ) );
}

} // namespace util

namespace util
{
namespace details
{

template< typename enable = void >
inline int64_t out_from_storage( std::chrono::system_clock::time_point & storage )
{
    return std::chrono::system_clock::to_time_t( storage );
}

} // namespace details
} // namespace util

int main(int argc, char * argv[])
{
    std::chrono::system_clock::time_point out = std::chrono::system_clock::now( );
    util::out_from_storage( out ); // error
    util::details::out_from_storage( out ); // no error

    return 0;
}

虽然这个示例相当简单,但代码是用于跨 DLL 边界编码(marshal)类型的实用程序库的一部分。有许多类似的实用函数和大量针对不同类型的专门化。在 VC 下一切都工作正常,我怀疑 VC 接受的只是一些虚假语法,但需要稍微更正确才能让 Clang 和 gcc 接受。对代码进行重大重新排序很困难,并且对系统进行重大重写以使用完全不同的方法来专门化转换函数(例如,删除 type_traits/enable_if 并使用标签调度或类似方法)是不切实际的。如果有人可以解释为什么 Clang 找不到 util::details::out_from_storage( std::chrono::system_clock::time_point & storage ) 的匹配函数调用,即使它很明显存在(并且 VC 可以找到它)我真的很感激。我对 Clang 和 gcc 很陌生。谢谢!

最佳答案

您有一个 out_from_storage 重载,无需显式提供模板参数即可调用,它依赖于:

std::is_trivial< typename std::decay< Ty >::type >::value

您使用 time_point 实例调用它,但这不是一个简单的类型,因为它没有一个简单的 default constructor 。因此,该重载已从集合中删除。

由于没有可行的重载,因此调用失败。

关于c++ - Clang 候选模板被忽略 : substitution failure (also fails to compile with gcc, VC 工作正常),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38406676/

相关文章:

c++ - 在 C/C++ 中获得正模的最快方法

C++ 字符串比较未按预期工作

c++ - Qt - 在新线程中处理 QTcpSocket

c++ - 如何从 C 的 "getcwd"函数返回一个 std::string

c++ - 通过引用线程对象传递取消引用的 `this` 指针,在函数对象构造函数中创建线程是好是坏?

c++ - C++中嵌套函数声明的范围

c++ - 结构初始化错误 : could not convert from ‘<brace-enclosed initializer list>’ to structure

c++ - 如果对 QObject::connect() 使用 lambda 函数,则使用 gcc 编译会失败

linux - 忽略 ‘system’ 的返回值,用属性 warn_unused_result 声明 ---GCC 编译器 linux

c++ - 如何创建可维护性高的共享对象?