2010-04-06 10 views
1
#include <stdlib.h> 
#include <iostream> 
#include <memory> 
#include "copy_of_auto_ptr.h" 
#ifdef _MSC_VER 
#pragma message("#include <string>") 
#include <string> 
// http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas 
#endif 

/* 
case 1-4 is the requirement of the auto_ptr. 
which form http://ptgmedia.pearsoncmg.com/images/020163371X/autoptrupdate/auto_ptr_update.html 
*/ 
/* 
case 1. 
(1) Direct-initialization, same type, e.g. 
*/ 
std::auto_ptr<int> source_int() { 
    // return std::auto_ptr<int>(new int(3)); 
    std::auto_ptr<int> tmp(new int(3)); 
    return tmp; 
} 

/* 
case 2. 
(2) Copy-initialization, same type, e.g. 
*/ 
void sink_int(std::auto_ptr<int> p) { 
    std::cout << "sink_int << " << *p << std::endl; 
} 

/* 
case 3. 
(3) Direct-initialization, base-from-derived, e.g. 
*/ 

class Base { 
public: 
    Base() { 
     std::cout << "creating Base object..." << std::endl; 
    } 
    virtual ~Base(){ 
     std::cout << "destoring Base object..." << std::endl; 
    } 
    virtual void go(){ 
     std::cout << "Base::go()" << std::endl; 
    } 
}; 

class Derived : public Base { 
public: 
    Derived() { 
     std::cout << "creating Derived object..." << std::endl; 
    } 
    ~Derived(){ 
     std::cout << "destoring Derived object..." << std::endl; 
    } 
    void go(){ 
     std::cout << "Derived::go()" << std::endl; 
    } 
}; 

std::auto_ptr<Derived> source_derived() { 
    // return std::auto_ptr<Derived>(new Derived()); 
    std::auto_ptr<Derived> tmp(new Derived()); 
    return tmp; 
} 

/* 
case 4. 
(4) Copy-initialization, base-from-derived, e.g. 
*/ 
void sink_base(std::auto_ptr<Base> p) { 
    p->go(); 
} 

int main(void) 
{ 
    /* 
    // auto_ptr 
    */ 
    // case 1. // auto_ptr 
    std::auto_ptr<int> p_int(source_int()); 
    std::cout << *p_int << std::endl; 

    // case 2. // auto_ptr 
    sink_int(source_int()); 

    // case 3. // auto_ptr 
    std::auto_ptr<Base> p_derived(source_derived()); 
    p_derived->go(); 

    // case 4. // auto_ptr 
    sink_base(source_derived()); 

    return 0; 
} 

Dans Eclipse (GNU C++ exe -v gcc Version 3.4.5 (MinGW-vista r3 spéciale).) Il est deux erreurs de compilation:Pourquoi est-ce qu'il peut être compilé dans GNU/C++, ne peut pas être compilé dans VC++ 2010 RTM?

Description Resource Path Location Type initializing argument 1 of void sink_base(std::auto_ptr<Base>)' from result of std::auto_ptr<_Tp>::operator std::auto_ptr<_Tp1>() [with _Tp1 = Base, _Tp = Derived]' auto_ptr_ref_research.cpp auto_ptr_ref_research/auto_ptr_ref_research 190 C/C++ Problem

Description Resource Path Location Type no matching function for call to `std::auto_ptr::auto_ptr(std::auto_ptr)' auto_ptr_ref_research.cpp auto_ptr_ref_research/auto_ptr_ref_research 190 C/C++ Problem

Mais il est vrai dans VS2010 RTM.

Questions:

  1. Quel support compilateur pour la norme ISO C++?

  2. Le contenu du cas 4 est le problème "auto_ptr & auto_ptr_ref que vous voulez résoudre?"

+1

Voulez-vous dire la version finale de Visual Studio 2010? Il n'a pas encore RTMed. –

+0

Il ne peut pas être compilé avec g ++ 4.4.1, au moins après avoir supprimé des choses étranges - pourriez-vous supprimer tout le code qui ne cause pas de problèmes et des choses comme #include "copy_of_auto_ptr.h". –

Répondre

7

Je pense qu'une version raccourcie est:

struct X 
{ 
    X() {} 
    X(X&); 
}; 

X make() { return X(); } 

void receive(X) { } 

int main() 
{ 
    receive(make()); 
} 

Notez la forme inhabituelle du constructeur de copie (à partir d'une référence non-const) qui empêche (par la norme, GCC est correct) la possibilité de copier -construit une instance à partir d'un temporaire (le résultat de make()).


La situation est beaucoup plus compliquée parce que std::auto_ptr tentatives de contourner les limitations résultant d'une enveloppe auto_ptr_ref. Cependant, puisque vous voulez également changer le type du pointeur, il se décompose probablement quelque part avec toutes ces conversions implicites et VC++ parvient à le compiler uniquement grâce à une extension non standard (permettant des valeurs de liaison à des références non constantes).

Le compilateur me dit exactement cela. Sur la ligne de problème:

warning C4239: nonstandard extension used : 'argument' : 
conversion from 'std::auto_ptr<_Ty>' to 'std::auto_ptr<_Ty> &' 

Quoi qu'il en soit, std::auto_ptr est un peu d'une expérience ratée avec la sémantique bizarre et dépréciée dans la norme suivante. En C++ 0x (par exemple avec gcc 4.4.1) cela fonctionnerait si vous remplaciez toutes les occurrences de auto_ptr par unique_ptr, et changiez la signature des fonctions de récepteur pour utiliser les références rvalue pour obtenir le transfert de propriété.

void sink_base(std::unique_ptr<Base>&& p); 
+0

> Voulez-vous dire le candidat à la version Visual Studio 2010? Il n'a pas encore RTMed. - James McNellis Il y a 8 heures pas la version RC, // c'est une version RTM qui sera publiée dans le futur mais c'est privé maintenant. mais la version de est écrite en 1994. –

+0

Elle ne peut pas être compilée avec g ++ 4.4.1, au moins après avoir supprimé des choses étranges - pourriez-vous supprimer tout le code qui ne cause pas de problèmes et des trucs comme #include? copy_of_auto_ptr.h ". - Neil Butterworth il ya 8 heures // désolé, je copie mon code à la main, j'ai oublié de le retirer de mon code publié. En fait, copy_of_auto_ptr est identique à auto_ptr, il copie le code source de STL, remplace 'auto_ptr' par 'copy_of_auto_ptr' sans aucune modification. c'est le comportement est correct. –