Two versions of generic functions?

Discussion in 'C++' started by Immortal Nephi, Apr 13, 2010.

  1. I create generic class. Non-unicode string and unicode string
    definitions are placed in generic class body. I am unable to place
    them into function body. I will have to create two separate
    functions. Both functions behave the same.
    First version of function is non-unicode and second version of
    function is unicode. Both functions take too much spaces in the
    source code. It would be nice to have only one function.
    How do I declare local type variable into function body? Local type
    variable will be string and wstring. The C++ Compiler will fail to
    compile and error message says redefinition sampleText variables.

    template< typename A, typename B, typename C >
    class Foo
    {
    public:
    Foo() {}
    ~Foo() {}

    void Print( A a, B &b, C &c );

    static const A text;
    static const A text2;
    };

    const std::string Foo< std::string, std::eek:stream, std::istream >::text
    =
    "Non-unicode --> Type your name: ";

    const std::wstring Foo< std::wstring, std::wostream, std::wistream
    >::text =

    L"Unicode --> Type your name: ";

    const std::string Foo< std::string, std::eek:stream, std::istream
    >::text2 =

    "\n\nNon-unicode --> Your name is ";

    const std::wstring Foo< std::wstring, std::wostream, std::wistream
    >::text2 =

    L"\n\nUnicode --> Your name is ";

    template< typename A, typename B, typename C >
    void Foo< A, B, C >::print( A a, B &b, C &c )
    {
    A sampleText;
    std::string sampleText = “Non-unicode string”;
    std::wstring sampleText = L“Unicode string”; // error redefinition

    A name;

    b << a << std::endl << text;
    c >> name;

    b << text2 << name << std::endl;
    }


    int main()
    {
    Foo< std::string, std::eek:stream, std::istream > f;
    f.Print( "Non-unicode String", std::cout, std::cin );

    Foo< std::wstring, std::wostream, std::wistream > f2;
    f2.Print( L"Unicode String", std::wcout, std::wcin );

    return 0;
    };
    Immortal Nephi, Apr 13, 2010
    #1
    1. Advertising

  2. On Apr 13, 1:10 pm, Victor Bazarov <> wrote:
    > Immortal Nephi wrote:
    > >    I create generic class.  Non-unicode string and unicode string
    > > definitions are placed in generic class body.  I am unable to place
    > > them into function body.  I will have to create two separate
    > > functions.  Both functions behave the same.
    > >    First version of function is non-unicode and second version of
    > > function is unicode.  Both functions take too much spaces in the
    > > source code.  It would be nice to have only one function.
    > >    How do I declare local type variable into function body?  Local type
    > > variable will be string and wstring.  The C++ Compiler will fail to
    > > compile and error message says redefinition sampleText variables.

    >
    > > template< typename A, typename B, typename C >
    > > class Foo
    > > {
    > > public:
    > >    Foo() {}
    > >    ~Foo() {}

    >
    > >    void Print( A a, B &b, C &c );

    >
    > >    static const A text;
    > >    static const A text2;
    > > };

    >
    > > const std::string Foo< std::string, std::eek:stream, std::istream >::text
    > > =
    > >    "Non-unicode --> Type your name: ";

    >
    > > const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >> ::text =

    > >    L"Unicode --> Type your name: ";

    >
    > > const std::string Foo< std::string, std::eek:stream, std::istream
    > >> ::text2 =

    > >    "\n\nNon-unicode --> Your name is ";

    >
    > > const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >> ::text2 =

    > >    L"\n\nUnicode --> Your name is ";

    >
    > > template< typename A, typename B, typename C >
    > > void Foo< A, B, C >::print( A a, B &b, C &c )
    > > {
    > >    A sampleText;
    > >    std::string sampleText = “Non-unicode string”;
    > >    std::wstring sampleText = L“Unicode string”; // error redefinition

    >
    > Isn't your 'A' type the type you need to declare 'sampleText'?  If so,
    > use it:
    >
    >       A sampleText;
    >
    > Since you want to initialize it here, you need a helper class that would
    > contain that string in its static member, something like
    >
    >    template<class ST> struct FooHelper {
    >        static const ST str;
    >    };
    >
    >    std::string const FooHelper<std::string>::str("narrow");
    >    std::wstring const FooHelper<std::wstring>::str(L"wide");




    >
    >     ...
    >
    >    template<typename A ...> void FOO<A,B,C>::print(...
    >
    >       A sampleText = FooHelper<A>::str;


    str variable is initialized in the global scope outside the function
    body. I want the data to be initialized into str inside function
    body.

    Print(….)
    {
    FooHelper<A>::str = “”;
    FooHelper<A>::str = L“”;

    A sampleText = FooHelper<A>::str;

    c >> sampleText;
    }

    Type c will select either cin or wcin.
    Immortal Nephi, Apr 13, 2010
    #2
    1. Advertising

  3. On Apr 13, 2:55 pm, Victor Bazarov <> wrote:
    > Immortal Nephi wrote:
    > > On Apr 13, 1:10 pm, Victor Bazarov <> wrote:
    > >> Immortal Nephi wrote:
    > >>>    I create generic class.  Non-unicode string and unicode string
    > >>> definitions are placed in generic class body.  I am unable to place
    > >>> them into function body.  I will have to create two separate
    > >>> functions.  Both functions behave the same.
    > >>>    First version of function is non-unicode and second version of
    > >>> function is unicode.  Both functions take too much spaces in the
    > >>> source code.  It would be nice to have only one function.
    > >>>    How do I declare local type variable into function body?  Local type
    > >>> variable will be string and wstring.  The C++ Compiler will fail to
    > >>> compile and error message says redefinition sampleText variables.
    > >>> template< typename A, typename B, typename C >
    > >>> class Foo
    > >>> {
    > >>> public:
    > >>>    Foo() {}
    > >>>    ~Foo() {}
    > >>>    void Print( A a, B &b, C &c );
    > >>>    static const A text;
    > >>>    static const A text2;
    > >>> };
    > >>> const std::string Foo< std::string, std::eek:stream, std::istream >::text
    > >>> =
    > >>>    "Non-unicode --> Type your name: ";
    > >>> const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >>>> ::text =
    > >>>    L"Unicode --> Type your name: ";
    > >>> const std::string Foo< std::string, std::eek:stream, std::istream
    > >>>> ::text2 =
    > >>>    "\n\nNon-unicode --> Your name is ";
    > >>> const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >>>> ::text2 =
    > >>>    L"\n\nUnicode --> Your name is ";
    > >>> template< typename A, typename B, typename C >
    > >>> void Foo< A, B, C >::print( A a, B &b, C &c )
    > >>> {
    > >>>    A sampleText;
    > >>>    std::string sampleText = “Non-unicode string”;
    > >>>    std::wstring sampleText = L“Unicode string”; // error redefinition
    > >> Isn't your 'A' type the type you need to declare 'sampleText'?  If so,
    > >> use it:

    >
    > >>       A sampleText;

    >
    > >> Since you want to initialize it here, you need a helper class that would
    > >> contain that string in its static member, something like

    >
    > >>    template<class ST> struct FooHelper {
    > >>        static const ST str;
    > >>    };

    >
    > >>    std::string const FooHelper<std::string>::str("narrow");
    > >>    std::wstring const FooHelper<std::wstring>::str(L"wide");

    >
    > >>     ...

    >
    > >>    template<typename A ...> void FOO<A,B,C>::print(...

    >
    > >>       A sampleText = FooHelper<A>::str;

    >
    > >    str variable is initialized in the global scope outside the function
    > > body.  I want the data to be initialized into str inside function
    > > body.

    >
    > You don't like a helper object, that's fine.  Create *two* overloaded
    > functions that simply return your literals:
    >
    >    std::string FooHelper(std::string const&) { return "narrow"; }
    >    std::wstring FooHelper(std::wstring const&) { return L"wide"; }
    >
    > You can make them static in your class if you like.
    >
    >
    >
    > > Print(….)
    > > {
    > >    FooHelper<A>::str = “”;
    > >    FooHelper<A>::str = L“”;

    >
    > Remove those.
    >
    >
    >
    > >    A sampleText = FooHelper<A>::str;

    >
    > Change to
    >
    >         A sampleText = FooHelper(A());
    >
    >
    >
    > >    c >> sampleText;
    > > }

    >
    > >    Type c will select either cin or wcin.

    >
    > Why do you need to initialize the string you're reading into, anyway?


    I already created two overloaded functions. I wrote first version of
    function. I used copy-paste to copy all my codes in its function body
    to second version of function. I rename to add prefix ‘w’ to cout,
    cin, string, and stringstream.
    The duplicated second version of function takes too much spaces in my
    source code. It seems unnecessary. I thought that I prefer to use
    only one function.
    You suggested FooHelper. You placed it in the file scope outside Foo
    class definition. I am trying to place it inside member function
    body. The local variables are restricted in one member function only.
    It looks like below.

    A sampleText;
    std::string sampleText = “Hello World!”; // non const string
    std::wstring sampleText = L“Hello World!”; // non const string

    A sampleText2;
    std::string sampleText2”; // uninitialized variable
    std::wstring sampleText2; // uninitialized variable

    What are you suggesting me to do?
    Can FooHelper be in member function body?
    Immortal Nephi, Apr 13, 2010
    #3
  4. On Apr 13, 3:36 pm, Victor Bazarov <> wrote:
    > Immortal Nephi wrote:
    > > On Apr 13, 2:55 pm, Victor Bazarov <> wrote:
    > >> Immortal Nephi wrote:
    > >>> On Apr 13, 1:10 pm, Victor Bazarov <> wrote:
    > >>>> Immortal Nephi wrote:
    > >>>>>    I create generic class.  Non-unicode string and unicode string
    > >>>>> definitions are placed in generic class body.  I am unable to place
    > >>>>> them into function body.  I will have to create two separate
    > >>>>> functions.  Both functions behave the same.
    > >>>>>    First version of function is non-unicode and second version of
    > >>>>> function is unicode.  Both functions take too much spaces in the
    > >>>>> source code.  It would be nice to have only one function.
    > >>>>>    How do I declare local type variable into function body?  Local type
    > >>>>> variable will be string and wstring.  The C++ Compiler will fail to
    > >>>>> compile and error message says redefinition sampleText variables.
    > >>>>> template< typename A, typename B, typename C >
    > >>>>> class Foo
    > >>>>> {
    > >>>>> public:
    > >>>>>    Foo() {}
    > >>>>>    ~Foo() {}
    > >>>>>    void Print( A a, B &b, C &c );
    > >>>>>    static const A text;
    > >>>>>    static const A text2;
    > >>>>> };
    > >>>>> const std::string Foo< std::string, std::eek:stream, std::istream >::text
    > >>>>> =
    > >>>>>    "Non-unicode --> Type your name: ";
    > >>>>> const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >>>>>> ::text =
    > >>>>>    L"Unicode --> Type your name: ";
    > >>>>> const std::string Foo< std::string, std::eek:stream, std::istream
    > >>>>>> ::text2 =
    > >>>>>    "\n\nNon-unicode --> Your name is ";
    > >>>>> const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >>>>>> ::text2 =
    > >>>>>    L"\n\nUnicode --> Your name is ";
    > >>>>> template< typename A, typename B, typename C >
    > >>>>> void Foo< A, B, C >::print( A a, B &b, C &c )
    > >>>>> {
    > >>>>>    A sampleText;
    > >>>>>    std::string sampleText = “Non-unicode string”;
    > >>>>>    std::wstring sampleText = L“Unicode string”; // error redefinition
    > >>>> Isn't your 'A' type the type you need to declare 'sampleText'?  If so,
    > >>>> use it:
    > >>>>       A sampleText;
    > >>>> Since you want to initialize it here, you need a helper class that would
    > >>>> contain that string in its static member, something like
    > >>>>    template<class ST> struct FooHelper {
    > >>>>        static const ST str;
    > >>>>    };
    > >>>>    std::string const FooHelper<std::string>::str("narrow");
    > >>>>    std::wstring const FooHelper<std::wstring>::str(L"wide");
    > >>>>     ...
    > >>>>    template<typename A ...> void FOO<A,B,C>::print(...
    > >>>>       A sampleText = FooHelper<A>::str;
    > >>>    str variable is initialized in the global scope outside the function
    > >>> body.  I want the data to be initialized into str inside function
    > >>> body.
    > >> You don't like a helper object, that's fine.  Create *two* overloaded
    > >> functions that simply return your literals:

    >
    > >>    std::string FooHelper(std::string const&) { return "narrow"; }
    > >>    std::wstring FooHelper(std::wstring const&) { return L"wide"; }

    >
    > >> You can make them static in your class if you like.

    >
    > >>> Print(….)
    > >>> {
    > >>>    FooHelper<A>::str = “”;
    > >>>    FooHelper<A>::str = L“”;
    > >> Remove those.

    >
    > >>>    A sampleText = FooHelper<A>::str;
    > >> Change to

    >
    > >>         A sampleText = FooHelper(A());

    >
    > >>>    c >> sampleText;
    > >>> }
    > >>>    Type c will select either cin or wcin.
    > >> Why do you need to initialize the string you're reading into, anyway?

    >
    > >    I already created two overloaded functions.

    >
    > Which ones?  I didn't see any.  You only mentioned them, but you didn't
    > post their bodies, not even declarations.
    >
    >  >  I wrote first version of
    >
    > > function.  I used copy-paste to copy all my codes in its function body
    > > to second version of function.  I rename to add prefix ‘w’ to cout,
    > > cin, string, and stringstream.
    > >    The duplicated second version of function takes too much spaces in my
    > > source code.  It seems unnecessary.  I thought that I prefer to use
    > > only one function.
    > >    You suggested FooHelper.  You placed it in the file scope outside Foo
    > > class definition.

    >
    > Uh... Yes.  Your class is called 'Foo'.  I suggested a class FooHelper,
    > which you didn't like.  Forget the class, just have two functions
    > instead.  No, you don't like that either!
    >
    >  >  I am trying to place it inside member function
    >
    > > body.

    >
    > Well, define a local class, then.  What's stopping you?  Place two
    > functions 'FooHelper' in that local class, overload them.  Of course
    > those are going to be duplicated since they will be instantiated along
    > with the member, but you probably don't care.
    >
    >  >  The local variables are restricted in one member function only.
    >
    > >    It looks like below.

    >
    > > A sampleText;
    > > std::string sampleText = “Hello World!”; // non const string
    > > std::wstring sampleText = L“Hello World!”; // non const string

    >
    > > A sampleText2;
    > > std::string sampleText2”; // uninitialized variable
    > > std::wstring sampleText2; // uninitialized variable

    >
    > >    What are you suggesting me to do?

    >
    > I've made many suggestions that you seem to dislike.  Well, I suggest
    > you go figure it out yourself, then.
    >
    > >    Can FooHelper be in member function body?

    >
    > Yes, in a local class.  I am *not* going to spell it out.  Your
    > homework, *you* do it.  OK?


    I spend many hours figuring how to place FooHelper in member function
    body. Unfortunately. C++ Compiler fails to compile and reports
    FooHelper must be placed in global scope or class scope. I do know
    that local class is legal to be placed in function body.
    I want to take your advice. I put FooHelper class in function body.
    I continue to figure out. If I am unable to do it, I will accept to
    use two version of functions instead.
    Immortal Nephi, Apr 13, 2010
    #4
  5. On Apr 13, 3:36 pm, Victor Bazarov <> wrote:
    > Immortal Nephi wrote:
    > > On Apr 13, 2:55 pm, Victor Bazarov <> wrote:
    > >> Immortal Nephi wrote:
    > >>> On Apr 13, 1:10 pm, Victor Bazarov <> wrote:
    > >>>> Immortal Nephi wrote:
    > >>>>>    I create generic class.  Non-unicode string and unicode string
    > >>>>> definitions are placed in generic class body.  I am unable to place
    > >>>>> them into function body.  I will have to create two separate
    > >>>>> functions.  Both functions behave the same.
    > >>>>>    First version of function is non-unicode and second version of
    > >>>>> function is unicode.  Both functions take too much spaces in the
    > >>>>> source code.  It would be nice to have only one function.
    > >>>>>    How do I declare local type variable into function body?  Local type
    > >>>>> variable will be string and wstring.  The C++ Compiler will fail to
    > >>>>> compile and error message says redefinition sampleText variables.
    > >>>>> template< typename A, typename B, typename C >
    > >>>>> class Foo
    > >>>>> {
    > >>>>> public:
    > >>>>>    Foo() {}
    > >>>>>    ~Foo() {}
    > >>>>>    void Print( A a, B &b, C &c );
    > >>>>>    static const A text;
    > >>>>>    static const A text2;
    > >>>>> };
    > >>>>> const std::string Foo< std::string, std::eek:stream, std::istream >::text
    > >>>>> =
    > >>>>>    "Non-unicode --> Type your name: ";
    > >>>>> const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >>>>>> ::text =
    > >>>>>    L"Unicode --> Type your name: ";
    > >>>>> const std::string Foo< std::string, std::eek:stream, std::istream
    > >>>>>> ::text2 =
    > >>>>>    "\n\nNon-unicode --> Your name is ";
    > >>>>> const std::wstring Foo< std::wstring, std::wostream, std::wistream
    > >>>>>> ::text2 =
    > >>>>>    L"\n\nUnicode --> Your name is ";
    > >>>>> template< typename A, typename B, typename C >
    > >>>>> void Foo< A, B, C >::print( A a, B &b, C &c )
    > >>>>> {
    > >>>>>    A sampleText;
    > >>>>>    std::string sampleText = “Non-unicode string”;
    > >>>>>    std::wstring sampleText = L“Unicode string”; // error redefinition
    > >>>> Isn't your 'A' type the type you need to declare 'sampleText'?  If so,
    > >>>> use it:
    > >>>>       A sampleText;
    > >>>> Since you want to initialize it here, you need a helper class that would
    > >>>> contain that string in its static member, something like
    > >>>>    template<class ST> struct FooHelper {
    > >>>>        static const ST str;
    > >>>>    };
    > >>>>    std::string const FooHelper<std::string>::str("narrow");
    > >>>>    std::wstring const FooHelper<std::wstring>::str(L"wide");
    > >>>>     ...
    > >>>>    template<typename A ...> void FOO<A,B,C>::print(...
    > >>>>       A sampleText = FooHelper<A>::str;
    > >>>    str variable is initialized in the global scope outside the function
    > >>> body.  I want the data to be initialized into str inside function
    > >>> body.
    > >> You don't like a helper object, that's fine.  Create *two* overloaded
    > >> functions that simply return your literals:

    >
    > >>    std::string FooHelper(std::string const&) { return "narrow"; }
    > >>    std::wstring FooHelper(std::wstring const&) { return L"wide"; }

    >
    > >> You can make them static in your class if you like.

    >
    > >>> Print(….)
    > >>> {
    > >>>    FooHelper<A>::str = “”;
    > >>>    FooHelper<A>::str = L“”;
    > >> Remove those.

    >
    > >>>    A sampleText = FooHelper<A>::str;
    > >> Change to

    >
    > >>         A sampleText = FooHelper(A());

    >
    > >>>    c >> sampleText;
    > >>> }
    > >>>    Type c will select either cin or wcin.
    > >> Why do you need to initialize the string you're reading into, anyway?

    >
    > >    I already created two overloaded functions.

    >
    > Which ones?  I didn't see any.  You only mentioned them, but you didn't
    > post their bodies, not even declarations.
    >
    >  >  I wrote first version of
    >
    > > function.  I used copy-paste to copy all my codes in its function body
    > > to second version of function.  I rename to add prefix ‘w’ to cout,
    > > cin, string, and stringstream.
    > >    The duplicated second version of function takes too much spaces in my
    > > source code.  It seems unnecessary.  I thought that I prefer to use
    > > only one function.
    > >    You suggested FooHelper.  You placed it in the file scope outside Foo
    > > class definition.

    >
    > Uh... Yes.  Your class is called 'Foo'.  I suggested a class FooHelper,
    > which you didn't like.  Forget the class, just have two functions
    > instead.  No, you don't like that either!
    >
    >  >  I am trying to place it inside member function
    >
    > > body.

    >
    > Well, define a local class, then.  What's stopping you?  Place two
    > functions 'FooHelper' in that local class, overload them.  Of course
    > those are going to be duplicated since they will be instantiated along
    > with the member, but you probably don't care.
    >
    >  >  The local variables are restricted in one member function only.
    >
    > >    It looks like below.

    >
    > > A sampleText;
    > > std::string sampleText = “Hello World!”; // non const string
    > > std::wstring sampleText = L“Hello World!”; // non const string

    >
    > > A sampleText2;
    > > std::string sampleText2”; // uninitialized variable
    > > std::wstring sampleText2; // uninitialized variable

    >
    > >    What are you suggesting me to do?

    >
    > I've made many suggestions that you seem to dislike.  Well, I suggest
    > you go figure it out yourself, then.
    >
    > >    Can FooHelper be in member function body?

    >
    > Yes, in a local class.  I am *not* going to spell it out.  Your
    > homework, *you* do it.  OK?

    Victor,

    To my conclusion: you saw my code above on the beginning of my post.
    You saw that text and text2 variables are defined in the Foo class
    scope.

    const std::string Foo< std::string, std::eek:stream, std::istream >::text
    = "Non-unicode --> Type your name: ";

    const std::wstring Foo< std::wstring, std::wostream, std::wistream
    >::text = L"Unicode --> Type your name: ";


    Notice that above? You do not need to use FooHelper because text
    variable is already in Foo class scope.

    …Print(…)
    {
    A sampleText = text; // without helper
    A sampleText = FooHelper<A>::str; // within helper
    //….
    }

    I have to accept the fact. I can’t put "Non-unicode --> Type your
    name: " and "Unicode --> Type your name: " in the function body, but I
    always place them in the Foo class scope.

    I wonder why all other member functions do not need to access text
    variable directly from Foo class scope because text variable belongs
    to Print() function. It should be inaccessible to all member
    functions because it treats to be local variable inside Print()
    function.
    Immortal Nephi, Apr 14, 2010
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Murat Tasan
    Replies:
    1
    Views:
    8,040
    Chaitanya
    Feb 3, 2009
  2. Xiangliang Meng
    Replies:
    1
    Views:
    1,592
    Victor Bazarov
    Jun 21, 2004
  3. Replies:
    2
    Views:
    434
  4. Tony Johansson

    generic functions(template functions)

    Tony Johansson, Aug 16, 2005, in forum: C++
    Replies:
    3
    Views:
    406
    Srini
    Aug 16, 2005
  5. minlearn
    Replies:
    2
    Views:
    454
    red floyd
    Mar 13, 2009
Loading...

Share This Page