【发布时间】:2017-10-17 02:48:59
【问题描述】:
我从标题中发现了 3 个编译器中似乎是一个令人难以置信的错误。以下代码使用 c++11 和 c++14 标准与所有三个编译器的最新版本一起编译,尽管它确实不应该,因为 "visit_detail" 函数对 "main" 不可见。
更正:我很愚蠢,实际上不是 GCC/Clang 中的错误,但似乎是我的 MSVC 版本中的错误。
#include <utility>
#include <iostream>
#include <type_traits>
namespace bug
{
using namespace std;
using size_t = unsigned long long;
namespace detail
{
struct visit_stop_t {};
constexpr bug::detail::visit_stop_t visit_stop = bug::detail::visit_stop_t();
template <typename Visitor, typename First, typename... Tail>
void visit_detail(Visitor&& vis, First&& first, Tail&&... tail)
{
// code, not necessairy to recreate bug
}
}
template <typename Visitor, typename... Variants>
void visit(Visitor&& vis, Variants&&... vars)
{
bug::detail::visit_detail(bug::forward<Visitor>(vis), bug::forward<Variants>(vars)..., bug::detail::visit_stop);
}
template <typename Visitor>
void visit(Visitor&& vis) = delete;
}
using namespace bug;
// dummy variant, used to test the code
// code is never actually used in this version
template <typename... T>
struct variant
{
static constexpr bug::size_t size() noexcept { return sizeof...(T); }
constexpr variant(int) noexcept {}
template <bug::size_t I>
constexpr int get() const noexcept { return 5; }
};
// simple example visitor
// code is never actually used in this version
struct visitor
{
int operator()(int x) { std::cout << x << std::endl; return x; }
double operator()(double x) { std::cout << x << std::endl; return x; }
};
int main()
{
visitor vis;
variant<int, double> var = 5;
// where the trouble is:
visit_detail(vis, var, bug::detail::visit_stop); // ADL: http://en.cppreference.com/w/cpp/language/adl
visit_detail(vis, var); // fails with GCC/Clang, no error with MSVC => MSVC bug maybe
std::cout << "Press enter to continue . . . ";
std::getchar();
return 0;
}
【问题讨论】:
-
我怀疑您看到的是 ADL 的实际应用
-
using size_t = unsigned long long;为什么?为什么?至少做using size_t = decltype(sizeof(int));之类的事情,或者更好的是,包括<cstddef>。 -
这只是一些快速而肮脏的代码示例,我将它们放在一起以显示错误实际上是什么
-
正如 Andrey 所说,这是 argument-dependent lookup,而不是错误。
-
很确定使用
bug::detail::visit_stop会将bud::detail::visit_detail带入作用域,因为参数也在同一个命名空间内。
标签: c++ c++11 gcc visual-c++ clang