Frage

In Visual C ++ (2008 und 2010), der folgenden Code kompiliert nicht mit dem folgenden Fehler:

#include <memory>

void Foo( std::shared_ptr< int >    test = ::std::make_shared< int >( 5 ) )
{
}

class P
{
    void
    Foo( std::shared_ptr< int > test = ::std::make_shared< int >( 5 ) )
    {
    }
};

Fehler C2039: 'make_shared': ist kein Mitglied von '`globalen Namensraum' '

Fehler C3861: 'make_shared': Bezeichner nicht gefunden

Es beschwert sich über die Definition von P :: Foo () nicht :: Foo ().

Weiß jemand, warum es gilt für Foo () ist ein Standard-Argument zu haben, mit std :: make_shared aber nicht P :: Foo ()?

War es hilfreich?

Lösung

Es sieht aus wie ein Fehler in dem Compiler. Hier ist der minimale Code zum Reproduzieren des Problems erforderlich:

namespace ns
{
    template <typename T>
    class test
    {
    };

    template <typename T>
    test<T> func()
    {
        return test<T>();
    }
}

// Works:
void f(ns::test<int> = ns::func<int>()) { }

class test2
{
    // Doesn't work:
    void g(ns::test<int> = ns::func<int>()) 
    { 
    }
};

Visual C ++ 2008 und 2010 sowohl Bericht:

Fehler C2783: 'ns::test<T> ns::func(void)': konnte nicht deduce Template-Argument für 'T'

Comeau hat keine Probleme mit diesem Code.

Andere Tipps

ich traf, was das gleiche Problem in meinem eigenen Code zu sein scheint. Der minimale Code, den ich es eingekocht, war dies:

namespace N
{
    template<typename T>
    T defaultValue()
    {
        return T();
    }

    template<typename T>
    void fun( const T& value = N::defaultValue<T>() ){}
}

int main(int argc, char* argv[])
{
    N::fun<int>();
    return 0;
}

Das ist etwas anders zu James McNellis Beispiel - und, wie ich glaube, unterstreicht die Tatsache, dass es die Namespace-Qualifikation im Standardargument initiliser ist, wo es schief geht

.

In diesem Fall default und Spaß ist im gleichen Namensraum, so dass Sie trivialer N entfernen :: von N :: default und es funktioniert.

Wenn default in einem anderen Namespace ist, dass Sie es immer noch entweder umgehen können es in dem lokalen Namensraum zu bringen mit, oder eine lokale Weiterleitung Template-Funktion zu schreiben, z.

namespace N1
{
    template<typename T>
    T defaultValue()
    {
        return T();
    }
}
namespace N2
{
    template<typename T>
    T defaultValueFwd()
    {
        return N1::defaultValue<T>();
    }

    template<typename T>
    void fun( const T& value = defaultValueFwd<T>() ){}
}

int main(int argc, char* argv[])
{
    N2::fun<int>();
    return 0;
}

Bit A einen Schmerz, aber machbar. Ich glaube, dass Sie diese Technik in dem make_shared Fall verwenden könnten, obwohl ich es nicht versucht habe.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top