Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++11] Dedukcja parametru szablonu

Ostatnio zmodyfikowano 2013-08-22 13:55
Autor Wiadomość
b00rt00s
Temat założony przez niniejszego użytkownika
[C++11] Dedukcja parametru szablonu
» 2013-08-21 22:58:42
Mam taki program:
C/C++
#include <type_traits>
#include <memory>


// first.h file
template < typename T >
struct smart_ptr_types;

template < typename T >
using shared_ptr_type = typename smart_ptr_types < T >::shared_ptr_type;

template < class T, class U >
inline shared_ptr_type < T > shared_ptr_type_static_cast( const shared_ptr_type < U >& r );


//second.h file

#include "first.h"

template < typename T >
struct smart_ptr_types
{
    typedef std::shared_ptr < T > shared_ptr_type;
};

template < class T, class U >
inline shared_ptr_type < T > shared_ptr_type_static_cast( const shared_ptr_type < U >& r )
{
    return std::static_pointer_cast < T >( r );
}


//main.cpp file

#include "second.h"

class A { };
class B
    : public A
{ };


int main() {
    shared_ptr_type < A > b( new B() );
   
    shared_ptr_type < B > c = shared_ptr_type_static_cast < B >( b );
}

I taki błąd kompilacji:

../../main.cpp: In function 'int main()':
error: no matching function for call to 'shared_ptr_type_static_cast(shared_ptr_type<A>&)'
  shared_ptr_type<B> c = shared_ptr_type_static_cast<B>(b);
                                                         ^
note: candidate is:
note: template<class T, class U> shared_ptr_type<T> shared_ptr_type_static_cast(shared_ptr_type<U>&)
 inline shared_ptr_type<T> shared_ptr_type_static_cast( const shared_ptr_type<U>& r )
                           ^
note:   template argument deduction/substitution failed:
note:   couldn't deduce template parameter 'U'
  shared_ptr_type<B> c = shared_ptr_type_static_cast<B>(b);
                                                         ^

Jak widać kompilator nie może wydedykować drugiego parametru szablonowej funkcji, choć sprawa wydaje się oczywista. Pomaga oczywiście wywołanie:
shared_ptr_type < B > c = shared_ptr_type_static_cast < B, A >( b );

Jednak bardzo mi zależy na tym, aby kompilator mógł samodzielnie wydedukować drugi parametr szablonu.

W czym leży błąd?
P-90730
DejaVu
» 2013-08-21 23:34:18
C/C++
#include <type_traits>
#include <memory>


template < typename T >
struct smart_ptr_types
{
    typedef std::shared_ptr < T > shared_ptr_type;
};

template < typename T >
using eksperyment = typename smart_ptr_types < T >::shared_ptr_type;

int main() { return 0; }

http://stackoverflow.com​/questions/2795023​/c-template-typedef


Sprawdź czy to działa pod Twoim kompilatorem. Visual C++ 2012 chyba nie wspiera tej części standardu.
P-90732
DejaVu
» 2013-08-21 23:36:13
C/C++
template < typename T >
struct smart_ptr_types;

template < typename T >
using shared_ptr_type = typename smart_ptr_types < T >::shared_ptr_type;

generalnie to z Twojego kodu nie ma prawa zadziałać, bowiem deklarujesz tylko i wyłącznie istnienie struktury, a nie tego co ona zawiera. Pisząc:
C/C++
smart_ptr_types < T >::shared_ptr_type
definicja struktury smart_ptr_types musi być już znana - w Twoim przypadku jest ona nieznana.
P-90733
b00rt00s
Temat założony przez niniejszego użytkownika
» 2013-08-21 23:43:26
generalnie to z Twojego kodu nie ma prawa zadziałać, bowiem deklarujesz tylko i wyłącznie istnienie struktury, a nie tego co ona zawiera. Pisząc:
(...)
definicja struktury smart_ptr_types musi być już znana - w Twoim przypadku jest ona nieznana.

1. W main.cpp definicja struktury smart_ptr jest już znana, bo dołączam oba nagłówki.
2. Gdyby w tym właśnie tkwił problem, to jakim cudem zadziałała ta linia:
shared_ptr_type < A > b( new B() );

Nie twierdzę, że mam rację, ale wydaje mi się, że gdybyś Ty miał rację, to działanie kompilatora w tej kwestii byłoby w mojej opinii niespójne.

P.S. Właśnie sprawdziłem, że działa również takie przypisanie:
std::shared_ptr < A > x = b;

P.S.2. Zapomniałem dodać: używam GCC 4.8.1
P-90734
b00rt00s
Temat założony przez niniejszego użytkownika
» 2013-08-22 00:06:45
Uprościłem nieco program ale błąd kompilacji nadal wsytępuje. Oto uproszczony kod:
C/C++
template < typename T >
struct smart_ptr_types
{
    typedef std::shared_ptr < T > shared_ptr_type;
};

template < typename T >
using shared_ptr_type = typename smart_ptr_types < T >::shared_ptr_type;

template < class T, class U >
inline shared_ptr_type < T > shared_ptr_type_static_cast( const shared_ptr_type < U >& r )
{
    return std::static_pointer_cast < T >( r );
}


class A { };
class B
    : public A
{ };


int main() {
    shared_ptr_type < A > b( new B() ); //działa
    std::shared_ptr < A > x = b; //działa
    shared_ptr_type < B > c = shared_ptr_type_static_cast < B >( b ); //nie działa
}

To jawnie dowodzi, że brak definicji klasy smart_ptr_types przed deklaracją szablonu shared_ptr_type  nie był źródłem problemu.
P-90735
DejaVu
» 2013-08-22 00:09:50
C/C++
#include <type_traits>
#include <memory>


template < typename T >
struct smart_ptr_types
{
    typedef std::shared_ptr < T > shared_ptr_type;
};

template < typename T >
using shared_ptr_type = typename smart_ptr_types < T >::shared_ptr_type;

template < class T, class U >
inline shared_ptr_type < T > shared_ptr_type_static_cast( const U & r )
{
    return std::static_pointer_cast < T >( r );
}

class A { };
class B
    : public A
{ };


int main() {
    shared_ptr_type < A > b( new B() );
   
    shared_ptr_type < B > c = shared_ptr_type_static_cast < B >( b );
}
P-90737
b00rt00s
Temat założony przez niniejszego użytkownika
» 2013-08-22 00:14:16
OK, to rozwiązuje mój problem. Zastanawia mnie jednak jak w poprzednim przypadku działa kompilator. Na tzw. chłopski rozum wszystko było jasne i jednoznaczne. Czegoś mu jednak brakowało do wydedukowania tego parametru. Chciałbym to zrozumieć.
P-90738
DejaVu
» 2013-08-22 00:19:12
Po prostu miałeś niezgodność typów.
C/C++
//do takiej postaci rozwijałeś szablon:
void funkcja( const szablon < szablon < int > >& argument )
{
}

//...
szablon < int > zmienna;
funkcja( zmienna ); //niezgodność typów
P-90740
« 1 » 2
  Strona 1 z 2 Następna strona