Zel*_*ron 2 c++ gcc clang visual-c++ c++11
我从标题中发现了3个编译器中看起来像是一个令人头疼的错误.下面的代码使用c ++ 11和c ++ 14标准编译所有三个编译器的最新版本,即使它真的不应该因为"main"看不到"visit_detail"函数.
更正:我是愚蠢的,实际上并不是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;
}
Run Code Online (Sandbox Code Playgroud)
您所遇到的是一个C++特性,称为依赖于参数的查找,或简称为ADL.基本上,如果在f没有显式限定函数的情况下调用函数,编译器将f在您传递的参数的名称空间中查找.
这使得operator<<IO流无需资格即可工作:
std::cout << 100; // finds std::operator<<(std::ostream&, int);
Run Code Online (Sandbox Code Playgroud)
在您的特定情况下,参数bug::detail::visit_stop是让编译器visit_detail在bug::detail命名空间内查找.
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |