此代码可与GCC和Clang一起正常使用。当使用自定义类型而不是std :: chrono :: duration时,它在MSVC中工作正常。在operator+
上使用operator*
时,效果很好。它可以在2018年之前的MSVC(而不是2017/2015年)上正常工作。
我是否遗漏了任何明显的内容,或者这仅仅是MSVC中的错误? https://godbolt.org/z/EUWV7e
为完整起见,这是上述链接中的测试用例:
#include <chrono>
namespace A {
class Foo {
public:
int mCount;
constexpr explicit Foo(int count) : mCount( count ) {}
};
template<class Rep, class Period>
inline Foo
operator*(const Foo foo1, const std::chrono::duration<Rep, Period> duration) {
return Foo(foo1.mCount * duration.count());
}
// For testing purposes, this is identical to operator* above.
template<class Rep, class Period>
inline Foo
operator+(const Foo foo1, const std::chrono::duration<Rep, Period> duration) {
return Foo(foo1.mCount * duration.count());
}
}
int main() {
A::Foo foo1(50);
// This fails to compile for some reason? Changing the '*' to a '+' works fine however.
auto foo2 = foo1 * std::chrono::minutes(15);
return foo2.mCount;
}
答案 0 :(得分:1)
来自<chrono>
:
template<class _Rep1,
class _Rep2,
class _Period2> inline
constexpr typename enable_if<is_convertible<_Rep1,
typename common_type<_Rep1, _Rep2>::type>::value,
duration<typename common_type<_Rep1, _Rep2>::type, _Period2> >::type
operator*(
const _Rep1& _Left,
const duration<_Rep2, _Period2>& _Right) ...
请注意,由于std::chrono::minutes
为duration<int, ratio<60>>
-_Rep2
为int
。现在common_type<_Rep1, _Rep2>
扩展为(请参见<type_traits>
):
struct common_type // <Foo, int>
{ // type is common type of Foo and int for two arguments
typedef typename decay<
decltype(false ? declval<Foo>() : declval<int>())
>::type type;
};
您观察到的错误是有条件的操作员抱怨,SFINAE并未以某种方式“拦截”。如果您从Foo的ctor中删除explicit
,它将消失。
我对SFINAE行为的细节并不十分熟悉,但是cppreference.com有一个有趣的提示:
仅立即类型和表达式中的失败 函数类型或其模板参数类型或其上下文的上下文 显式说明符(自C ++ 20起)是SFINAE错误。如果评价 类型/表达式的替换会引起诸如 模板专业化的实例化,生成一个 隐式定义的成员函数等,这些副作用中的错误 被视为硬错误。
我不确定这是否适用于您的情况...如果确实如此-则MS编译器是正确的,但是其std lib有问题。如果不是,则可能是编译器中的一个问题。
编辑:显然,MS与SFINAE已有problems了...
答案 1 :(得分:0)
我已通过https://developercommunity.visualstudio.com/content/problem/381899/adl-sfinae-bug-in-mvc20152017-when-using-stdchrono.html向MSVC小组报告了此问题,他们已经确认这是MSVC中的错误,并且已在最新版本的MSVC2017中修复。感谢您的讨论!