Gå til innhold

template<int V> struct Int2Type{};


Anbefalte innlegg

#include <iostream>


template<int V>
struct Int2Type {
}; // struct Int2Type


template<bool HAS_OUT>
class Test {
public:
template<typename T>
void doIt(T& obj)
{
 doIt(obj, Int2Type<HAS_OUT>());
} // doIt()


private:
template<typename T>
void doIt(T& obj, Int2Type<true>)
{
 std::cout << obj.out() << std::endl;
} // doIt()

template<typename T>
void doIt(T& obj, Int2Type<false>)
{
 std::cout << "object does not have a out()-method" << std::endl;
 // alternate solution here.
} // doIt()
}; // class Test


class A {
public:
char* out()
{
 return("A::out()");
}
}; // class A


class B {
public:
}; // class B



int main()
{
using namespace std;
A a;
B b;

Test<true> t1; 
t1.doIt(a);

Test<false> t2; // true here would give problems.
t2.doIt(b);


return(0);
} // main()

 

..sitter å blar igjennom Andreis bok for andre gang, og måtte paste noe kode. Rett og slett en genial og enkel løsning på et problem. :]

 

Man bruker overloading basert på typene (som man legger til fra Int2Type) til argumentene i funksjonen.

 

Det hele løses @ compile-time (raskere), i motsetning til å vente med å løse det run-time v.h.a. en if(have_out) -sak; noe som eventuellt ville gått litt tregere hvis det i det hele tatt var mulig (det går ikke her).

 

Siden doIt(T&) er definert inline i klasse-deklarasjonen, blir det ikke noe tap der heller.

 

Boka anbefales virkelig på det sterkeste: http://www.amazon.co.uk/exec/obidos/ASIN/0201704315/ (for viderekommende C++ -programmerere)

Endret av søppel
Lenke til kommentar
Videoannonse
Annonse

Helt enig at denne boka er helt genial :) Kjøpte den to-tre måneder etter den kom ut i sin tid, og brukte mye tid på å fordøye og lære teknikker som den beskriver. Tenker spesielt på hvordan han bruker C++ teknikker til å implementere mer eller mindre avanserte design patterns.

 

Vil også anbefale Herb Sutters sine "Exceptional C++" bøker. De er også for middels til viderekommende C++ programmere.

 

Ellers har vi jo "Designs Patterns" boka som etter min mening hører hjemme i enhver seriøs programmerers bokhylle; uavhengig om man koder f.eks. Java eller C++.

 

Bokhylla mi:

 

"The C++ Programming Language" Bjarne

"Modern C++ Design" Andrei A.

"Effective C++" Scott Meyers

"More Effective C++" Scott Meyers

"Effective STL" Scott Meyers

"Exceptional C++" Herb Sutter

"More Exceptional C++" Herb Sutter

"Design Patterns" GoF

"Refactoring" Martin Fowler

 

..pluss en del mer biblioteksorienterte bøker (OpenGL, .NET, MFC, ATL, osv) og to UML bøker jeg ikke husker forfatterne på i farta.

Lenke til kommentar

Hva omhandler "Refactoring"? (Jada, jeg vet at jeg kan søke osv, men det er minst like greit å få høre det her, syns jeg).

 

Min bokhylle er litt mer tom, den består foreløpig bare av:

 

The C++ Programming Language (Bjarne)

The Design and Evolution of C++ (Bjarne)

Effective C++

 

Men, nye bøker kommer fortløpende hver gang finansene tillater det :)

Lenke til kommentar

Her går det i:

 

# Modern C++ Design: Applied Generic and Design Patterns (Andrei Alexandrescu)

# The C++ Programming Language, Special Ed. (Bjarne Stroustrup)

# Discrete Mathematics for New Technology, 2nd. Ed. (R. Garnier, J. Taylor)

# Understanding The Linux Kernel, 2nd. Ed. (Bovet & Cesati)

# Introduction to the Theory of Computation (Sipser)

# Core Techniques and Algorithms in Game Programming (Sánchez)

# 3D Math Primer, for Graphics and Game Development (Dunn, Parberry)

 

Edit:

..og + en hel haug e-books. Disse oppgraderes til papirformat ettersom jeg finner ut at det er verdt investeringen. :]

Endret av søppel
Lenke til kommentar
  • 3 uker senere...

Hei igjen,

Nå har jeg fått ennå en ny bok, "C++ Templates, The Complete Guide". Veldig fin.

 

..og jeg har kommet litt lengre i "Modern C++ Design" og har støtt på et par problemer her og der og har en løsning på ett av dem jeg tenkte jeg kunne paste her. På side 25 er det en kodesnutt for "Compile Time Assertions" som ikke gir noen mening for mine kompilere i hvertfall.

 

Så her er en løsning som funker hos meg:

 

template<bool EXPR, typename ERROR_MSG>
struct CompileTimeError : public ERROR_MSG {
};

template<typename ERROR_MSG>
struct CompileTimeError<true, ERROR_MSG> {
};


#define M_compileTimeCheck(expr, msg) \
{ \
 typedef void COMPILE_TIME_ERROR_##msg; \
 (void)sizeof(CompileTimeError<expr, COMPILE_TIME_ERROR_##msg>); \
} 


int main()
{
 M_compileTimeCheck(false, DetteErFeilmeldingen);

return(0);
} // main()

 

Dette gir meg feilmeldingen:

invalid use of `main::COMPILE_TIME_ERROR_DetteErFeilmeldingen'

..og det er dette vi er ute etter, altså en "compile time" brukerdefinert feilmelding.

 

Endres linjen:

M_compileTimeCheck(false, DetteErFeilmeldingen);

..til..

M_compileTimeCheck(true, DetteErFeilmeldingen);

..skal den kompilere uten problemer.

 

Jeg bruker GCC 3.4; fungerer dette hos dere?

Kanskje noen har nytte av dette. :]

 

Edit:

http://scm.nostdal.net/cgi-bin/viewcvs.cgi....viewcvs-markup

http://scm.nostdal.net/cgi-bin/viewcvs.cgi....viewcvs-markup

Blir det ikke lekkert? :]

Endret av søppel
Lenke til kommentar

Sliter her ..

template<typename T>
struct A {
typedef double Result;
}; 

template<typename T>
struct B {
};

template<typename T>
struct C {
typedef A<B<T> >::Result Result; /* error: type `A<B<T> >' is not derived from type `C<T>' */
};

int main()
{
return(0);
}

 

GCC 3.4, Linux.

 

ugh .. typename gjorde susen:

typedef typename A<B<T> >::Result Result;

 

Hvorfor kan den ikke automatisk gå ut i fra at det er snakk om en type egentlig?

 

Uansett .. litt snedig melding fra GCC denne gangen synes jeg.

Endret av søppel
Lenke til kommentar

Grunnen er at når C parses, veit ikke kompilatoren hva T er for noe. Og da er det umulig for den å skjønne om A<B<T> >::Result er en type, enum, objekt e.l.

 

Standarden sier at et "dependant name" (som her er A<B<T> >::Result siden den avhenger av hva T er) ikke skal forutsettes å være en type med mindre den er prefixet med typename. Teksten i standarden er kanskje klarere:

 

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

 

Det finnes mange artikler om emnet. Et søk på "dependant names" og typename bør vi resultater. Ellers kan du lese om det "More Exceptional C++" og jeg tror "Thinking C++ Vol. 2" har noe om emnet.

Lenke til kommentar

MSVC++ 7.1 ga forøvrig følgende tilbakemeldinger:

 

warning C4346: 'A<B<T>>::Result' : dependent name is not a type

prefix with 'typename' to indicate a type

 

error C2146: syntax error : missing ';' before identifier 'Result'

 

error C2501: 'C<T>::Result' : missing storage-class or type specifiers

Lenke til kommentar

I en del tilfeller, som søppel sitt, skal det være mulig for kompilatoren å dedusere at det er snakk om en type ut i fra konteksten. Eldre utgaver av GCC godtok jo også slike deklarasjoner, med en advarsel om at slik bruk var "deprecated". I More Exceptional C++ kommer Sutter med et eksempel hvor det blir umulig for parseren å skille, dog.

Lenke til kommentar
I More Exceptional C++ kommer Sutter med et eksempel hvor det blir umulig for parseren å skille, dog.

 

*nysjerrig*

Kunne jeg sett det?

 

Edit:

warning: `typename xxxxxx' is implicitly a typename

warning: implicit typename is deprecated, please see the documentation for details

 

Det er vel noe slikt GCC kommer med til vanlig, eller har kommet med tidligere i hvertfall. Mulig situasjonen i ex. mitt er forvirrende for kompileren (flere muligheter).

Endret av søppel
Lenke til kommentar

Det aktuelle eksempelet fra Sutter:

template<typename T>
class X_base
{
public:
 typedef T instantiated_type;
};

template<typename A, typename B>
class X : public X_base<B>
{
public:
 bool operator()( const instantiated_type &i ) const
 {
     return i != instantiated_type();
 }
};

Så vidt jeg kan se er problemet som følger: Kompilatoren vet ikke om instantiated_type er en type før X instansieres (med konkrete parametere), siden instantiated_type kan referere til noe helt annet i en spesialisering av X_base. Kompilatoren kan heller ikke gjette det ved parsing av:

return i != instantiated_type();

.

 

Nå har jeg eksperimentert litt med G++ 3.3, og ICC 8. G++ ser ut til å gå ut ifra at instantiated_type er en type pga. at den standard implementasjonen av X_base (ikke spesialisert) deklarerer den som en type. Dermed klager den på at det ikke finnes noen type instantiated_type i en spesialisert X_base hvor instantiated_type er et objekt.

 

ICC derimot ser ut til å utsette en del avgjørelser til X_base instansieres og kompilerer faktisk uten feil, selv om jeg skulle spesialisere X_base, og deklarere instantiated_type som et objekt (med operator()).

Lenke til kommentar

Ah, ok; noe slikt da:

 

#include <iostream>

using namespace std;


template<typename T>
class XBase {
public:
typedef T Result;
}; 

template<>
class XBase<int> {
public:
int Result;
}; 


template<typename A>
class X : public XBase<A> {
public:
bool operator()(typename XBase<A>::Result const& i)
{
 return i == typename XBase<A>::Result();
} 
}; 


int main()
{
X<char> x1;
cout << x1(0) << endl;

X<int> x2; // ** BOOOOM! **
cout << x2(0) << endl;
return(0);
}

Endret av søppel
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...