2017-05-17 4 views
2

Ich entdeckte, was scheint, ein geisteskranker Bug in den 3 Compiler aus dem Titel. Der folgende Code wird mit den neuesten Versionen aller drei Compiler kompiliert, die die Standards C++ 11 und C++ 14 verwenden, obwohl es wirklich nicht sein sollte, da die Funktion "visit_detail" für "main" nicht sichtbar ist.C++ MSVC/GCC/Clang Compiler-Bug

Korrektur: Ich war dumm, nicht wirklich ein Bug in GCC/Clang, scheint ein Bug in meiner MSVC-Version zu sein.

#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; 
} 
+4

Ich vermute, Sie sehen ADL in Aktion –

+3

'using size_t = unsigned long lang;' Warum? Warum? Mach wenigstens etwas wie 'using size_t = declltype (sizeof (int));', oder noch besser: ''. – InternetAussie

+0

es ist nur ein paar schnelle und schmutzige Code-Beispiel, die ich zusammen, um zu zeigen, was der Fehler tatsächlich ist – Zeldhoron

Antwort

5

Was Sie erleben ist eine Funktion ++ C genannt argument-dependent lookup oder ADL kurz. Wenn Sie eine Funktion f aufrufen, ohne es explizit zu qualifizieren, sucht der Compiler in den Namespaces der Argumente, die Sie übergeben haben, nach f.

Dies ist, was operator<< für IO ermöglicht, ohne dass Qualifikationen arbeiten Ströme:

std::cout << 100; // finds std::operator<<(std::ostream&, int); 

In Ihrem speziellen Fall ist das Argument bug::detail::visit_stop für visit_detail innerhalb des bug::detail Namespace den Compiler-Look macht.

+0

hat gerade den Beitrag aktualisiert, "visit_detail (vis, arg)" in "main" funktioniert auch mit msvc – Zeldhoron

+0

@Zeldhoron Habe es gerade auf gcc.godbolt.com getestet und sowohl GCC als auch Clang lehnen die zweite Zeile ab. – HolyBlackCat

+0

ja, auch mit ihnen getestet, gleich, so MSVC Bug – Zeldhoron