此代码适用于 GCC 和 Clang。当使用自定义类型而不是 std::chrono::duration 时,它在 MSVC 中工作正常。在 operator*
上使用 operator+
时效果很好。它适用于 MSVC pre 2018 而不是 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;
}
最佳答案
来自 <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;
};
您观察到的错误是有条件的运算符(operator)投诉,不知何故未被 SFINAE“拦截”。如果删除 explicit
来自 Foo 的 ctor——它会消失。
我不是很熟悉 SFINAE 行为的细节,但是 cppreference.com有好奇的笔记:
Only the failures in the types and expressions in the immediate context of the function type or its template parameter types or its explicit specifier (since C++20) are SFINAE errors. If the evaluation of a substituted type/expression causes a side-effect such as instantiation of some template specialization, generation of an implicitly-defined member function, etc, errors in those side-effects are treated as hard errors.
我不确定这是否适用于您的情况...如果适用——那么 MS 编译器是正确的,但他们的标准库有问题。如果不是——那么它可能是编译器中的一个问题。
编辑:显然 MS 有 problems在 SFINAE 呆了一段时间...
关于c++ - MSVC C++ ADL 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53289393/