Jump to content
  • Advertisement
Sign in to follow this  
kelaklub

Warning

This topic is 5032 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I get the following warnings when I try to compile the following source using g++. I don't understand their recommendation to fix it. Any help would be appreciated. Thanks. ************************************************************************ cl_bitFlag.h:34: warning: friend declaration `std::ostream& operator<<(std::ostream&, cBasicBitFlags<tType>&)' declares a non-template function cl_bitFlag.h:34: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning ************************************************************************
template < typename tType > class cBasicBitFlags;

template < typename tType >
inline tType util_SetBit( int i )
{
    return tType( static_cast < tType > (1) << i );
};

template < typename tType >
class cBasicBitFlagsProxy
{
public:

    cBasicBitFlagsProxy(int idx, cBasicBitFlags < tType > * ptr) : m_index(idx), m_bits(ptr){}

    void operator = (bool b)
    {
        b ? m_bits->set(m_index) : m_bits->unset(m_index);
    }

    operator bool () const
    {
        return m_bits->isSet(m_index);
    }

private:
    int m_index;
    cBasicBitFlags < tType > * m_bits;
};

template < typename tType >
class cBasicBitFlags
{
    friend inline ostream & operator << (ostream & o, cBasicBitFlags < tType > & bits);

public:
    cBasicBitFlags();
    cBasicBitFlags(tType flags);
    cBasicBitFlags(const cBasicBitFlags < tType > & other);

    bool  isSet(int bit) const;
    void  set(int bit);
    void  unset(int bit);
    int   size() const;
    void  setData(tType t);
    tType data() const;

    cBasicBitFlags < tType > operator | (const cBasicBitFlags < tType > & other);
    cBasicBitFlags < tType > operator & (const cBasicBitFlags < tType > & other);
    cBasicBitFlags < tType > operator ^ (const cBasicBitFlags < tType > & other);
    cBasicBitFlags < tType > operator ~ ();
    
    bool operator == (const cBasicBitFlags < tType > & other) const;
    bool operator != (const cBasicBitFlags < tType > & other) const;

    cBasicBitFlagsProxy < tType > operator [] (int idx);
    const cBasicBitFlagsProxy < tType > operator [] (int idx) const;

    ///
    /// Extracts a certain number of bits from the bitfield and places them at the
    /// starting bits in the returned bit field.
    cBasicBitFlags < tType > extract(int idx, int num);

    string toString() const;

private:
    tType m_flags;
};

template< typename tType >
string cBasicBitFlags < tType >::toString() const
{
    string str;
    str.reserve(size());
    for (int i = 0; i < size(); ++i)
        str += (isSet(i) ? "1" : "0");
    return str;
}

template< typename tType >
inline ostream& operator << (ostream & o, cBasicBitFlags < tType > & bits)
{
    o << bits.toString().c_str();
    return o;
}

template < typename tType >
cBasicBitFlags<tType>::cBasicBitFlags(): m_flags(0){}

template < typename tType >
cBasicBitFlags<tType>::cBasicBitFlags(tType flags): m_flags(flags){}

template < typename tType >
cBasicBitFlags < tType >::cBasicBitFlags(const cBasicBitFlags < tType > & other): m_flags(other.m_flags){}

template < typename tType >
bool cBasicBitFlags < tType >::isSet(int bit) const
{
    return (m_flags & util_SetBit < tType >(bit)) != 0;
}

template < typename tType >
void cBasicBitFlags < tType >::set(int bit)
{
    m_flags |= util_SetBit < tType > (bit);
}

template < typename tType >
void cBasicBitFlags < tType >::unset(int bit)
{
    m_flags &= ~util_SetBit < tType > (bit);
}

template < typename tType >
int cBasicBitFlags < tType >::size() const
{
    return sizeof(tType) * 8;
}

template < typename tType >
cBasicBitFlagsProxy < tType > cBasicBitFlags < tType >::operator [] (int idx)
{
    return cBasicBitFlagsProxy<tType>(idx, this);
}

template < typename tType >
const cBasicBitFlagsProxy < tType > cBasicBitFlags < tType >::operator [] (int idx) const
{
    return cBasicBitFlagsProxy < tType >(idx, const_cast < cBasicBitFlags < tType > * >(this));
}

template < typename tType >
tType cBasicBitFlags < tType >::data() const
{
    return m_flags;
}
/*
template< typename tType >
cBasicBitFlags<tType>::operator tType () const
{
return m_flags;
}
*/
template < typename tType >
cBasicBitFlags < tType > cBasicBitFlags < tType >::operator | (const cBasicBitFlags < tType > & other)
{
    return cBasicBitFlags<tType>( m_flags | other.data() );
}

template < typename tType >
cBasicBitFlags<tType> cBasicBitFlags < tType >::operator & (const cBasicBitFlags < tType > & other)
{
    return cBasicBitFlags<tType>( m_flags & other.data() );
}

template < typename tType >
cBasicBitFlags < tType > cBasicBitFlags < tType >::operator ^ (const cBasicBitFlags < tType > & other)
{
    return cBasicBitFlags < tType > (m_flags ^ other.data());
}

template < typename tType >
cBasicBitFlags < tType > cBasicBitFlags < tType >::operator ~ ()
{
    return cBasicBitFlags<tType>(~m_flags);
}

template < typename tType >
bool cBasicBitFlags < tType >::operator == (const cBasicBitFlags < tType > & other) const
{
    return m_flags == other.data();
}

template < typename tType >
bool cBasicBitFlags < tType >::operator != (const cBasicBitFlags < tType > & other) const
{
    return m_flags != other.data();
}

template < typename tType >
cBasicBitFlags < tType > cBasicBitFlags<tType>::extract(int idx, int num)
{
    tType d = m_flags << ( size() - (idx + num) );
    d >>= (size() - num);
    return cBasicBitFlags<tType>(d);
}

template < typename tType >
void cBasicBitFlags < tType >::setData(tType t)
{
    m_flags = t;
}

// Common bit sizes.
typedef cBasicBitFlags<unsigned char>    bits8_t;
typedef cBasicBitFlags<unsigned short>   bits16_t;
typedef cBasicBitFlags<unsigned int>     bits32_t;
typedef cBasicBitFlags<unsigned __int64> bits64_t;


Share this post


Link to post
Share on other sites
Advertisement
Hi,

Just a quick response, no time for checking so I hope it works. [wink]

The warning tells you that the declared friend function is not templated, and it isn't. But I've got a <tType> in there and everything! Yep, but you forgot to declare it templated by placing template<typename tType> in front of the declaration of the function, like so:


template<typename tType>
friend inline ostream & operator << (ostream & o, cBasicBitFlags < tType > & bits);


Secondly, templated functions, if I recall correctly and if I don't someone will correct me [wink], need to be defined entirely as they can not be forward declared without a function body; that would be the nature of templated functions.

So give it a try, and let me know if I got it wrong at this hour. I'm goin' to bed. [wink]

BTW Templated friend functions are a no-go for Visual C++ 6, I case you wish to port any of your code to that platform. Visual C++ 7 should be fine though.

hth,
CipherCraft

Share this post


Link to post
Share on other sites
Unfortunately I already tried that, but end up getting the following errors...

In file included from main.h:4,
from main.cpp:1:
cl_bitFlag.h:34: declaration of `class tType'
cl_bitFlag.h:31: shadows template parm `class tType'

I don't think that is the solution because the class(cBasicBitFlags) in which the function is declared is already templated. Thanks anyway.

Share this post


Link to post
Share on other sites
Quote:
Original post by CipherCraft
Hi,

Just a quick response, no time for checking so I hope it works. [wink]

The warning tells you that the declared friend function is not templated, and it isn't. But I've got a <tType> in there and everything! Yep, but you forgot to declare it templated by placing template<typename tType> in front of the declaration of the function, like so:


template<typename tType>
friend inline ostream & operator << (ostream & o, cBasicBitFlags < tType > & bits);


Secondly, templated functions, if I recall correctly and if I don't someone will correct me [wink], need to be defined entirely as they can not be forward declared without a function body; that would be the nature of templated functions.

So give it a try, and let me know if I got it wrong at this hour. I'm goin' to bed. [wink]

BTW Templated friend functions are a no-go for Visual C++ 6, I case you wish to port any of your code to that platform. Visual C++ 7 should be fine though.

hth,
CipherCraft


Actually, templated functions can be forward-declared just like any other function. However, you cannot abstract the implementations away into a separate source file in most compilers due to non-compliance with the standard (you should be able to use the export keyword for this purpose).

Share this post


Link to post
Share on other sites
Quote:
Original post by Thunder_Hawk
Quote:
Original post by CipherCraft
Hi,

Just a quick response, no time for checking so I hope it works. [wink]

[snip]



Actually, templated functions can be forward-declared just like any other function.


Yeah, I see that now, even in my own code. [wink]

Quote:
Original post by Thunder_Hawk
However, you cannot abstract the implementations away into a separate source file in most compilers due to non-compliance with the standard (you should be able to use the export keyword for this purpose).


True, in practise the entire definition must be available if you want to use it. However, I did not know that the standard defines otherwise. Could you point me to more info on that? I'm still intending to get a copy of the standard and my Stroustrup is at home right now. [wink]

On the shadow issue... The easy wait out would be to still use the declaration I've provided, but rename the template argument for your friend function. This shadowing is a known 'problem' with g++; it thinks you don't know what you're doing and accidentaly used the same name twice for different things.

hth,
CipherCraft

Share this post


Link to post
Share on other sites
It's funny but when I place the implementation of the function within the class I don't get any warnings. Like so...


template < typename tType >
class cBasicBitFlags
{
friend inline ostream & operator << (ostream & o, cBasicBitFlags < tType > & bits)
{
o << bits.toString().c_str();
return o;
}
.
.
.



I find this pretty strange because I always thought friend functions are supposed to be declared inside the class and defined outside the class.

Share this post


Link to post
Share on other sites
Hi,

I thought this whole thing looked familair... Then I remembered: I've read about it in Exceptional C++ style by Herb Sutter.

Item 8 discusses befriending templates. It tells us that the standard has the following two ways to properly define a templated function as a friend of a class:


// First
friend void Function (Type& inArgument);

// Second
friend void Function<> (Type& inArgument);

// Third, which is a equivalent to the second
friend void Function<Type> (Type& inArgument);


Now get this: nearly all compilers don't understand the first option! So let's not use that one. The second (and therefore the third too) option is understood more, but prominently lacking are all gcc implementations (that you are using) and msvc6.

By adding a template to the class containing the templated friend you make matters worse, since those poor compilers have no idea of what's happening then.

The guideline by Sutters states that if you want to declare a templated function a friend, then use the second option; that way you're clear on the fact that it's a templated function you're referring to and more compilers will understand what you mean.

There's an entire discussion in that book about this; I'm not gonna infringe on anyones copyright adn type it here, so I'm just going to recommend it to anyone. [wink] It's an interesting read with tantalizing advice as: 'never check if new succeeded', and 'never use the auto or register keywords since they are whitespace anyway'.

hth,
CipherCraft

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!