Explicit specialization of class members.

J

JC

I'm having a problem getting an explicit specialization to work
properly. I have a class like this, declared in a header:

class SomeClass {
template <typename T> class Nested {
void function ();
};
};

I also have the generic implementation Nested::function() in that same
header:

template <typename T> void SomeClass::Nested<T>::function () {
// ...
}

However, I want to specialize function() for a certain type, e.g. a
double. So the explicit specialization is:

template <> void SomeClass::Nested<double>::function () {
}

The problem is, if I put that in the header, the linker complains
about the function being defined in multiple object files. However, if
I put it in a source file, then the other source files that include
that header don't see the explicit specialization.

How can I make this work so that the linker is happy, and the explicit
specialization is used everywhere?

Thanks,
Jason
 
J

jasonc

I'm having a problem getting an explicit specialization to work
properly. I have a class like this, declared in a header:

class SomeClass {
  template <typename T> class Nested {
    void function ();
  };

};

I also have the generic implementation Nested::function() in that same
header:

template <typename T> void SomeClass::Nested<T>::function () {
  // ...

}

However, I want to specialize function() for a certain type, e.g. a
double. So the explicit specialization is:

template <> void SomeClass::Nested<double>::function () {

}

The problem is, if I put that in the header, the linker complains
about the function being defined in multiple object files. However, if
I put it in a source file, then the other source files that include
that header don't see the explicit specialization.


I also tried explicitly instantiating SomeClass::Nested<double> in the
header:

template SomeClass::Nested<double>;

And moving the definition for <double> into a source file, but the
compiler complained that the <double> template had already been
instantiated (when trying to compile the definition).
 
Joined
Mar 27, 2009
Messages
8
Reaction score
0
JC said:
I'm having a problem getting an explicit specialization to work
properly. I have a class like this, declared in a header:

class SomeClass {
template <typename T> class Nested {
void function ();
};
};

I also have the generic implementation Nested::function() in that same
header:

template <typename T> void SomeClass::Nested<T>::function () {
// ...
}

However, I want to specialize function() for a certain type, e.g. a
double. So the explicit specialization is:

template <> void SomeClass::Nested<double>::function () {
}

The problem is, if I put that in the header, the linker complains
about the function being defined in multiple object files. However, if
I put it in a source file, then the other source files that include
that header don't see the explicit specialization.

How can I make this work so that the linker is happy, and the explicit
specialization is used everywhere?

Thanks,
Jason


Weired - because the following code compiles perfectly for me and returns the appropriate output:

Code:
class SomeClass {
public:
  template <typename T> class Nested {
  public:
    void function ();
  };
  void test();
};

template <typename T> void SomeClass::Nested<T>::function () {
  cout << "generic"<<endl;
}

template <> void SomeClass::Nested<double>::function () {
  cout << "double"<<endl;
}

void SomeClass::test(){
  Nested<int> t;
  Nested<double> t1;
  t.function();
  t1.function();
}

int main()
{
  SomeClass s;
  s.test();
  return 0;
}

//output:
// generic
// double

I use gcc version 4.3.2
 
A

Alf P. Steinbach

* JC:
I'm having a problem getting an explicit specialization to work
properly. I have a class like this, declared in a header:

class SomeClass {
template <typename T> class Nested {
void function ();
};
};

I also have the generic implementation Nested::function() in that same
header:

template <typename T> void SomeClass::Nested<T>::function () {
// ...
}

However, I want to specialize function() for a certain type, e.g. a
double. So the explicit specialization is:

template <> void SomeClass::Nested<double>::function () {
}

The problem is, if I put that in the header, the linker complains
about the function being defined in multiple object files. However, if
I put it in a source file, then the other source files that include
that header don't see the explicit specialization.

How can I make this work so that the linker is happy, and the explicit
specialization is used everywhere?

Try adding "inline". :)

Not sure about the specialization stuff though because as I recall there are
some tricky rules disallowing what you can specialize, for no good reason.

But regarding the linker issue, a complete specialization of a function template
(which per C98 is the only kind of specialization, the apparent partial
specializations being technically overloads) is a real function, not a template
anymore, and so it has an address etc. obeys usual rules, hence "inline".


Cheers & hth.,

- Alf
 
V

Vladyslav Lazarenko

How can I make this work so that the linker is happy, and the explicit
specialization is used everywhere?

Thanks,
Jason

Jason,

Specify your specialized template method as "inline", like this:

template <>
inline // <------------- there you go
void SomeClass::Nested<double>::function () {
}

Another way to do that, I think, is using external templates. However,
external templates are not supported by most of C++ compilers,
unfortunately.

Good luck!
 
Joined
Mar 27, 2009
Messages
8
Reaction score
0
Oh! I think I understand the problem.

Most likely - some other file (which doesn't include your header file, but is linked to your project) either specialize or just used the function SomeClass::Nested<double>::function().

If that happens - then the definition for that function exists in both that file and your file, hence double-defined (no pun intended :) )

All you need to do is find all the files instancing SomeClass::Nested<double> and make sure they include your header :)

If you can't do that - you can't redefine SomeClass::Nested<double>::functio()...
 
J

jasonc

Specify your specialized template method as "inline", like this:

Ah, thanks! Works perfect now. I forgot about that... I think all the
web application development I've been doing recently has dulled my C++
a little...

Thanks!
Jason
 
A

Andrey Tarasevich

JC said:
I'm having a problem getting an explicit specialization to work
properly. I have a class like this, declared in a header:

class SomeClass {
template <typename T> class Nested {
void function ();
};
};

I also have the generic implementation Nested::function() in that same
header:

template <typename T> void SomeClass::Nested<T>::function () {
// ...
}

However, I want to specialize function() for a certain type, e.g. a
double. So the explicit specialization is:

template <> void SomeClass::Nested<double>::function () {
}

The problem is, if I put that in the header, the linker complains
about the function being defined in multiple object files. However, if
I put it in a source file, then the other source files that include
that header don't see the explicit specialization.

How can I make this work so that the linker is happy, and the explicit
specialization is used everywhere?

Normally, you should be able to declare/define the explicitly
specialized function just like an ordinary function. Which means that
you should be able to put the _declaration_ of the specialization into
the header file

template <> void SomeClass::Nested<double>::function();

and then place the _definition_ into one and only one implementation file

template <> void SomeClass::Nested<double>::function() {
}

This works fine with GCC, for example. MSVC 2005 fails to compile it
though, which I believe is a bug in the compiler.

(MSVC fails to "instantiate" the "unused" specialized definition, thus
resulting in no definition for the linker. I believe explicit
specializations of function templates are supposed to be treated as
ordinary function definitions, i.e. "instantiated" unconditionally).
 
L

litb

I'm having a problem getting an explicit specialization to work
properly. I have a class like this, declared in a header:

class SomeClass {
  template <typename T> class Nested {
    void function ();
  };

};

I also have the generic implementation Nested::function() in that same
header:

template <typename T> void SomeClass::Nested<T>::function () {
  // ...

}

However, I want to specialize function() for a certain type, e.g. a
double. So the explicit specialization is:

template <> void SomeClass::Nested<double>::function () {

}

The problem is, if I put that in the header, the linker complains
about the function being defined in multiple object files. However, if
I put it in a source file, then the other source files that include
that header don't see the explicit specialization.

You have to tell the files that include your header that there is an
explicit specialization of that member function done at another place:

template <> void SomeClass::Nested<double>::function ();

Put that into the header. Including files will then note this and know
about the specialization. This is stated by the Standard at 14.7.3/6 :

If a template, a member template or the member of a class template is
explicitly specialized then that specialization shall be declared
before the first use of that specialization that would cause an
implicit instantiation to take place, in every translation unit in
which such a use occurs; no diagnostic is required. [...]
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top