2016-07-16 59 views
1

我遇到了Clang 3.5的問題。以下是一個獨立的repro。此代碼與VC12編譯。鏗鏘我收到以下錯誤:Clang候選模板被忽略:替換失敗(也無法用gcc編譯,VC工作正常)

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邊界封送類型的一大塊。有許多類似的效用函數和針對不同類型的大量專業化。在VC下所有的工作都很好,我懷疑VC接受的只是一些虛假的語法,但是對於Clang和gcc來說,接受它需要稍微更正確。重要的代碼重新排序是困難的,並且系統的重大改寫使用完全不同的方法來專門化轉換函數(例如,撤銷type_traits/enable_if和使用標籤調度或類似)是不切實際的。如果有人可以解釋爲什麼Clang找不到匹配的函數調用util :: details :: out_from_storage(std :: chrono :: system_clock :: time_point &存儲),即使它很清楚存在(並且VC可以找到它)我真的很感激它。我對Clang和gcc非常陌生。謝謝!

+1

請提供[mcve],這裏有很多代碼與您遇到的問題完全無關。 – Barry

+0

N.b. 'util :: details :: template out_from_storage('可以並且應該是'util :: details :: out_from_storage('在兩個地方都有。 – ildjarn

+4

作爲一般規則,如果MSVC不同意GCC和/或clang,MSVC是錯誤的。 – o11c

回答

3

你有out_from_storage一個重載是可調用沒有明確提供模板參數,它依賴於:

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

你用time_point實例調用它,但這不是一個簡單的類型因爲它沒有小事default constructor。因此,這個過載從集合中移除。

由於沒有可行的過載,因此呼叫失敗。

+0

util :: detail :: out_from_storage有兩個重載,它們都不需要模板參數。重新正確的是,依賴 'std :: is_trivial :: type> :: value' 的過載不匹配,因爲time_point不是微不足道的(這是故意的),而是 'template < typename enable = void> inline auto out_from_storage(std :: chrono :: system_clock :: time_point&storage) - > decltype(util :: det ails :: make_out_helper(storage)) ' 匹配,也不需要模板參數。 –

+0

如果我將main更改爲: int main(int argc,char * argv []) { // \t auto tp = sample :: time :: CurrentTime(); \t std :: chrono :: system_clock :: time_point out; \t util :: details :: out_from_storage(out); \t return 0; }' 它編譯得很好。這個問題與util :: out_from_storage有關。 –

+0

@JohnCuyle有'* util :: details :: out_from_storage'的三個重載。也許這是你的混亂之源。 – Barry

相關問題