473,569 Members | 2,542 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Selection of partial specialization blocked by namespace confusion

Hi folks,
I observed something that puzzles me. When I do

namespace xxx { using std::swap; }

it appears that xxx::swap and std::swap are not strictly equivalent. In
particular, I think that my implementation will only choose the partial
specialization for std::vector when std::swap is used.

Consider the following code (ignore the part implementing the timing):

#include <ctime>
#include <iostream>
#include <utility>
#include <string>

class timer {
private:

std::clock_t ticks;

public:

timer ( void )
: ticks ( std::clock() )
{}

std::clock_t passed ( void ) const {
return( std::clock() - ticks );
}

double seconds ( void ) const {
return( double( this->passed() ) / CLOCKS_PER_SEC );
}

}; // timer

class print_timer {
private:

std::ostream & o_str;
std::string banner;
timer watch;

public:

print_timer ( std::ostream & str, std::string msg = std::string() )
: o_str ( str )
, banner ( msg )
, watch ()
{}

~print_timer ( void ) {
o_str << banner << " " << watch.seconds() << "sec" << '\n';
}

}; // print_timer

#define PRINT_TIME print_timer print_timer_dum my
namespace xxx { using std::swap; }

#include <vector>
typedef std::vector< long unsigned > IntVector;
int main ( void ) {
{
IntVector a ( 20000000, 20000000 );
IntVector b ( 20000000, 20000000 );
{
PRINT_TIME( std::cout, "xxx::swap: " );
xxx::swap( a, b );
}
{
PRINT_TIME( std::cout, "std::swap: " );
std::swap( a, b );
}
{
PRINT_TIME( std::cout, "std::swap: " );
std::swap( a, b );
}
{
PRINT_TIME( std::cout, "xxx::swap: " );
xxx::swap( a, b );
}
{
PRINT_TIME( std::cout, "std::swap: " );
std::swap( a, b );
}
}
}
On my machine, this prints:

news_group> a.out
xxx::swap: 0.31sec
std::swap: 0sec
std::swap: 0sec
xxx::swap: 0.33sec
std::swap: 0sec
The different times strongly indicate that std::swap uses a partial
specialization for vectors whereas xxx::swap does not. Is that standard? If
so, why?
Best

Kai-Uwe Bux

Oct 7 '05 #1
7 2083
* Kai-Uwe Bux:

I observed something that puzzles me. When I do

namespace xxx { using std::swap; }

it appears that xxx::swap and std::swap are not strictly equivalent. In
particular, I think that my implementation will only choose the partial
specialization for std::vector when std::swap is used.


It seems you forgot to #include <vector>. Formally that would be reason
enough, I think, for odd behavior, and as a fix. However I don't understand
how the particular behavior you observed could come about.

With MSVC 7.1 the partial specialization for std::vector is used in both cases
(says the debugger), when <vector> is #include'd; try

#include <iostream>
#include <ostream>
#include <vector>

namespace xxx
{
using std::swap;
}

int main()
{
typedef std::vector<int > V;
std::cout << static_cast<voi d(*)(V&,V&)>( &std::swap ) << std::endl;
std::cout << static_cast<voi d(*)(V&,V&)>( &xxx::swap ) << std::endl;

//V a, b;
//std::swap( a, b );
//xxx::swap( a, b );
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 7 '05 #2
Alf P. Steinbach wrote:
* Kai-Uwe Bux:

I observed something that puzzles me. When I do

namespace xxx { using std::swap; }

it appears that xxx::swap and std::swap are not strictly equivalent. In
particular, I think that my implementation will only choose the partial
specialization for std::vector when std::swap is used.
It seems you forgot to #include <vector>. Formally that would be reason
enough, I think, for odd behavior, and as a fix. However I don't
understand how the particular behavior you observed could come about.


Well I did include <vector> (below the timer part), but it appears that
order does matter: if I do

#include <vector>
namespace xxx { using std::swap; }

the specialization is used and when I do

namespace xxx { using std::swap; }
#include <vector>

it is not. Is that formally correct?

With MSVC 7.1 the partial specialization for std::vector is used in both
cases (says the debugger), when <vector> is #include'd; try

#include <iostream>
#include <ostream>
#include <vector>

namespace xxx
{
using std::swap;
}

int main()
{
typedef std::vector<int > V;
std::cout << static_cast<voi d(*)(V&,V&)>( &std::swap ) << std::endl;
std::cout << static_cast<voi d(*)(V&,V&)>( &xxx::swap ) << std::endl;

//V a, b;
//std::swap( a, b );
//xxx::swap( a, b );
}


prints
1
1

but what does that tell me? (Sorry for being dense, I also had a look at the
assembler code, but that is all gibberish to me.)
Thanks

Kai-Uwe Bux
Oct 7 '05 #3
Kai-Uwe Bux wrote:
Well I did include <vector> (below the timer part), but it appears that
order does matter: if I do

#include <vector>
namespace xxx { using std::swap; }

the specialization is used and when I do

namespace xxx { using std::swap; }
#include <vector>

it is not. Is that formally correct?


I have verified this now:
#include <iostream>

namespace xxx {

template < typename T >
struct container {};

template < typename T >
void print ( T const & ) {
std::cout << "not specialied\n";
}

}

namespace yyy {

using xxx::print;

}

namespace xxx {

template < typename T >
void print ( container<T> const & ) {
std::cout << "specialize d for container\n";
}

}
int main ( void ) {
int i = 0;
xxx::container< int> c;

xxx::print(i);
xxx::print(c);

yyy::print(i);
yyy::print(c);
}
prints:

news_group> a.out
not specialied
specialized for container
not specialied
not specialied
As you can see, yyy::print is never specialized. Is that the correct
behavior?
Best

Kai-Uwe Bux
Oct 7 '05 #4
* Kai-Uwe Bux:
Alf P. Steinbach wrote:
* Kai-Uwe Bux:

I observed something that puzzles me. When I do

namespace xxx { using std::swap; }

it appears that xxx::swap and std::swap are not strictly equivalent. In
particular, I think that my implementation will only choose the partial
specialization for std::vector when std::swap is used.


It seems you forgot to #include <vector>. Formally that would be reason
enough, I think, for odd behavior, and as a fix. However I don't
understand how the particular behavior you observed could come about.


Well I did include <vector> (below the timer part), but it appears that
order does matter: if I do

#include <vector>
namespace xxx { using std::swap; }

the specialization is used and when I do

namespace xxx { using std::swap; }
#include <vector>

it is not. Is that formally correct?


The first is formally correct. The second, I don't know, but I think the code
is not correct and the observed behavior can be anything and thus correct.

With MSVC 7.1 the partial specialization for std::vector is used in both
cases (says the debugger), when <vector> is #include'd; try

#include <iostream>
#include <ostream>
#include <vector>

namespace xxx
{
using std::swap;
}

int main()
{
typedef std::vector<int > V;
std::cout << static_cast<voi d(*)(V&,V&)>( &std::swap ) << std::endl;
std::cout << static_cast<voi d(*)(V&,V&)>( &xxx::swap ) << std::endl;

//V a, b;
//std::swap( a, b );
//xxx::swap( a, b );
}


prints
1
1

but what does that tell me?


That Alf's fingers may produce code that compiles and seemingly works with one
particular compiler, without involving his brain?

The intent was to see whether the std::swap and xxx::swap was the same
function, in which case they'd have the same address.

Says g++:
vc_project.cpp: In function `int main()':
vc_project.cpp: 14: warning: the address of `void std::swap(std:: vector<_Tp,
_Alloc>&, std::vector<_Tp , _Alloc>&) [with _
_Tp = int, _Alloc = std::allocator< int>]', will always evaluate as `true'

To fix this add a C-cast or reinterpret_cas t to void*, i.e. like

(void*)static_c ast<void(*)(V&, V&)>( &std::swap )

which is Undefined Behavior or at best Unspecified Behavior (one cannot
officially, portably, cast a function pointer to void*), but hey, it's in the
service of Good.

I should just have let the program _compare_ the two pointers, with Defined
Behavior, and print something like "same function" or "different functions"...

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Oct 7 '05 #5
> Kai-Uwe Bux wrote:
Well I did include <vector> (below the timer part), but it appears
that order does matter: if I do

#include <vector>
namespace xxx { using std::swap; }
the specialization is used and when I do

namespace xxx { using std::swap; }
#include <vector>
it is not. Is that formally correct?
I have verified this now:

#include <iostream>

namespace xxx {

template < typename T >
struct container {};
template < typename T >
void print ( T const & ) {
std::cout << "not specialied\n";
}

// CCCC
}

namespace yyy {

using xxx::print; // AAAA

}

namespace xxx {

template < typename T >
void print ( container<T> const & ) {
std::cout << "specialize d for container\n";
} // BBBB
}

int main ( void ) {
int i = 0;
xxx::container< int> c;
xxx::print(i);
xxx::print(c); A compiler finds both CCCC and BBBB at the first phase of names lookup here
and thinks that there is no argument dependant lookup (ADL) needed. BBBB
is better.
yyy::print(i);
yyy::print(c); A compiler finds AAAA at the first phase of names lookup here and thinks
that there is no argument dependant lookup (ADL) needed. But it sees only
CCCC at the point of yyy::print declaration (AAAA).
}
prints:

news_group> a.out
not specialied
specialized for container
not specialied
not specialied
As you can see, yyy::print is never specialized. Is that the correct
behavior?

I believe yes. Let us consider an example with ADL which may help to understand
the "elegance" of C++ language:

#include <iostream>
namespace yyy {
template <class T1>
void f1(const T1 t1) {
print(t1);
}
}

namespace xxx {

template < typename T >
struct container {};

template < typename T >
void print ( T const & ) {
std::cout << "not specialied\n";
}
// YYYY

template < typename T >
void print ( container<T> const & ) {
std::cout << "specialize d for container\n";
}
// ZZZZ

}
int main ( void ) {
int i = 0;
xxx::container< int> c;

xxx::print(i);
xxx::print(c);

//yyy::f1(i);
// HHHH

yyy::f1(c);
// GGGG
}

A compiler can find nothing at GGGG at the first phase of names lookup and
performs ADL then. YYYY and ZZZZ are both found. Great. But HHHH will never
work because the fundumental types are not bound to a namespace and xxx::print(int)
cannot be found by ADL.

--
Michael Kochetkov
Oct 7 '05 #6
Michael Kochetkov wrote:

[highly appreciated long and detailed explanation pointing out where and
when ADL kicks in snipped]

I am not sure about the ADL thing -- quite honestly, it is somewhat a
mystery to me. But I figured from a note in 7.3.3/9 that there is a
difference in class templates and function templates. Therefore, the
following code finds the partial specializations regardless of order:

#include <iostream>

namespace xxx {

template < typename T >
struct container {};

template < typename T >
struct print_traits {

static
void act ( void ) {
std::cout << "not specialized\n";
}

};

template < typename T >
void print ( T const & ) {
print_traits<T> ::act();
}

}

namespace yyy { using xxx::print; }

namespace xxx {

template < typename T >
struct print_traits < container<T> > {

static
void act ( void ) {
std::cout << "specialize d for container\n";
}

};

}

int main ( void ) {
int i = 0;
xxx::container< int> c;

xxx::print(i);
xxx::print(c);

yyy::print(i);
yyy::print(c);
}

prints:
not specialized
specialized for container
not specialized
specialized for container
n
Do you happen to know why ADL is done for class templates and not for
function templates?
Again, many thanks.
Best

Kai-Uwe Bux
Oct 8 '05 #7
> Michael Kochetkov wrote:

[highly appreciated long and detailed explanation pointing out where
and when ADL kicks in snipped]

I am not sure about the ADL thing -- quite honestly, it is somewhat a
mystery to me. But I figured from a note in 7.3.3/9 that there is a I understand it the following way: ADL is performed when a function name
cannot be found by the ordinary lookup. It is probably not quite strict but
shall suit a practicing C++ programmer. More over I start to beging to believe
that ADL shall be preffered for names resolutions while designing large systems.
It may considerably improve the reliability of a system -- the less declarations
a compiler see the better. And of course one shall be happy if a compiler
will always look for a function name that resides in a namespace of it's
arguments. Just my opinion.
difference in class templates and function templates. Therefore, the
following code finds the partial specializations regardless of order: There is no partial specialization of function templates in C++ language.
That shall explain the case you are talking about.

#include <iostream>

namespace xxx {

template < typename T >
struct container {};
template < typename T >
struct print_traits {
static
void act ( void ) {
std::cout << "not specialized\n";
}
};

template < typename T >
void print ( T const & ) {
print_traits<T> ::act();
}
}

namespace yyy { using xxx::print; } If you had a specialization of print somewhere below a compiler will not
consider it because it will not be a partial specialization of the print.
And no ADL will take place because the function is found pretty well with
the ordinary lookup. But print_traits<T> ::act(); call shall consider partial
specializations of print_traits. Again, no ADL.

[...] Do you happen to know why ADL is done for class templates and not for
function templates?

I have mentioned ADL and have given an example for completeness only. There
cannot be an ADL in you case. You cannot write:
namespace yyy { using xxx::print; }
or
namespace yyy { using print; }

having not declared xxx::print somewhere before. The proper functions _are_
found the ordinary way in your case. And a compiler just picks up the most
suitable one. But it chooses it from the functions that were found before
the point of namespace yyy { using xxx::print; } declaration.
You may use parameterised classes instead of functions indeed. It would make
life a bit of easier. But you might want to consider the ADL approach I have
mentioned above -- functions declarations are not visible and a compeler
looks for them in the namespaces of threir arguments. And of course you would
have use unqualified functions' names in this case.

--
Michael Kochetkov
Oct 8 '05 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
6837
by: Paul MG | last post by:
Hi Template partial specialization always seems like a fairly straightforward concept - until I try to do it :). I am trying to implement the input sequence type (from Stroustrup section 18.3.1, 'Iseq'). I want the version for containers that he gives, but also to provide a specialization for construction from a pair<It,It> (eg because...
9
2534
by: Philip Lawatsch | last post by:
Hi I'd like to implement some kind if type traits myself, but I have to support broken compilers (like visual studio) that do not support Partial Specialization. My first shot was something like this: ----8<--- typedef char IsPODForListArrayTrue;
1
1587
by: Laax | last post by:
Hi all, I get Partial Specilization error while trying to compile the following code in environment . I could not locate the error. Please show me some light. Thanks. Here is the complete code(developed by someone else sometime back). ----------------------------------------------------------------
8
7657
by: Agent Mulder | last post by:
Hi group, I have a problem with partial template specialization. In the code below I have a template struct Music with one method, play(), and three kinds of music, Jazz, Funk and Bach. When I specialize Music<Bach>, I expect that the original play() method is available in the specialization, but it is not. How can I fix this? -X
1
1726
by: BekTek | last post by:
I'm still confused about the template partial specialization which is used in many libraries.. due to lack of introduction for beginner.. Could you tell me about that in short? Thanks in advance..
5
6572
by: Levent | last post by:
Hi, Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1): #include <iostream> template<class T, unsigned N> struct Foo { void func(); }; template<class T, unsigned N>
8
4784
by: Ferdi Smit | last post by:
I've never understood the rationale of allowing partial, but not explicit specialization for classes at non-namespace scope. Ie.: struct A { template <typename T1, typename T2> struct B {}; // this is not allowed: template <> struct B<int, float> {};
4
1844
by: Alfonso Morra | last post by:
Does VC 7.1 support template specialization and partial specialization ?
1
2217
by: Ioannis Gyftos | last post by:
Hello, First the code :) /////////////////////////////////////////////////////////////////////////////////// // in another header file namespace LJC{
0
7700
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7924
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8125
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7676
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7974
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5219
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3653
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3642
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2114
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.