how to specialize templated member functions of non-templated classes? - c++

suppose I have a file alpha.h:
class Alpha {
public:
template<typename T> void foo();
};
template<> void Alpha::foo<int>() {}
template<> void Alpha::foo<float>() {}
If I include alpha.h in more than one cpp file and compile with GCC 4.4, it complains there are multiple definitions of foo<int> and foo<float> across multiple object files. Makes sense to me, so I change the last two lines to:
template<> extern void Alpha::foo<int>() {}
template<> extern void Alpha::foo<float>() {}
But then GCC says:
explicit template specialization
cannot have a storage class
ok... so how am I supposed to do this correctly? I'm worried that C++ doesn't allow what I'm trying to do in the first place, in which case is there a good idiom that will accomplish the same thing?

use inline keyword
template<> inline void Alpha::foo<int>() {}
alternatively, provide implementation in separate cpp file

You can forward declare as well as the inline option:
// .h
template<> void Alpha::foo<int>();
//.cpp
template<> void Alpha::foo<int>() {}

From the ODR point of view, a fully (explicitly) specialized template is no longer a template, so it is subject to the same ODR principles as a non-template entity of the same kind. (There are some exceptions from that rule, I believe, but it is good enough for our purposes).
In your case, for ODR purposes a fully specialized function template is an ordinary function. So, as an ordinary function it should be declared in the header file and defined in one and only one implementation file.

No separate declaration or inline keywork is required. PF below working code.
#include<iostream>
class temp
{
public:
template <class T>
T add1(T a, T b)
{
return (a + b);
}
};
template<>
std::string temp::add1<std::string>(std::string aa, std::string bb)
{
return aa+bb;
}
int main()
{
temp *tc = new temp();
std::cout << tc->add1<float>(5.7, 4.5) << std::endl;
std::cout << tc->add1<std::string>("my ","program") << std::endl;
}
output is :
10.2
my program

Related

C++20 template compilation passes

I am having a problem with the changes that were made to the way C++ templates are compiled, between the C++17 and 19 standards. Code that used to compile in VS2017 throws a compiler error since I upgraded to VS2019 or VS2022.
Situations have to do with the fact that the compiler now runs a basic syntax check on the template definition when it sees this definition ("first pass") and not only when the template is actually used.
Code example 1:
class Finder
{
template<typename T>
T convert_to(HANDLE h)
{
return Converters::Converter<T>::Convert(get_data(h));
}
};
Here, the template class Converter<> resides in namespace Converters, and get_data is a member function of Finder which returns something that can be passed into the Convert function.
Since we're dealing with templates, this code sits in a header file "Finder.h". The header file doesn't #include "Converters.h". Finder.h is shared across several projects, some of which don't even know the Converters.h file namespace.
As long as no code calls the MyClass::convert_to<> function, this compiles in VS2017, but not so in VS2019 and VS2022:
error C3861: 'Converters': identifier not found
The obvious solution is, of course, to #include "Converters.h" either in this header file, or in the precompiled headers file. However, as was said, Converters.h is not known in all places which use MyClass. Another solution would be to use archaic #define CONVERTERS_H in the Converters.h header and enclose the function definition in #ifdef CONVERTERS_H, but this looks really ugly.
My question is: Is there a way to prevent the compiler from doing this "first pass"? Or to re-write this code so that it compiles? I don't mind if it's MS specific; no other compiler will ever see the code.
Code example 2:
class MyClass2
{
template<class T>
static void DoSomething(T* ptr) { static_assert(false, "Don't do this"); }
// lots more member functions, most of them 'static'
};
template<> void MyClass::DoSomething(CWnd* ptr) { /*some useful code*/ }
/// and some more specializations of DoSomething
The intention is that the static_assert should emit an error message whenever DoSomething is called with an argument for which no explicit specialization of this template function is defined. This worked in VS2017, but in VS2022, the "first pass" of the compiler triggers the static_assert.
Again, I wonder how I could achieve this effect, other than by replacing the static_assert by a run-time assertion.
Or am I thinking into a completely wrong direction?
Thanks
Hans
The first case requires a forward declaration of some kind, that's unavoidable.
The second case, though, can be handled with just a minor change.
#include <type_traits>
class CWnd {};
class MyClass2
{
public:
template<class T, class Y=T>
static void DoSomething(T* ptr) { static_assert(!std::is_same_v<Y,T>, "Don't do this"); }
};
template<> void MyClass2::DoSomething(CWnd* ptr) { /*some useful code*/ }
void foo()
{
int a;
CWnd b;
MyClass2::DoSomething(&a); // ERROR
MyClass2::DoSomething(&b); // OK
}
(partial answer)
To fix MyClass2, the usual trick is to make false depend on T, so that the first pass does not trigger the assert.
// dependent false
template <typename>
constexpr bool dep_false() { return false; }
class MyClass2
{
template<class T>
static void DoSomething(T* ptr) {
static_assert(dep_false<T>(), "Don't do this");
}
// lots more member functions, most of them 'static'
};
// specialization example
template<>
void MyClass2::DoSomething<int>(int* ptr) {
std::cout << "int* is OK\n";
}

Declare non-template function in a template class?

NOTE: this post is different from this one: Declare non-template friend function for template class outside the class, so please read my question before marking it as duplicate.
I want to declare a non-template friend function inside a class template, and the arguments and return type of that friend function is unrelated to the template argument. How should I do that?
Please note it is different from that previous question because in that question, arguments and return type of that friend function is related to the template argument.
Example, adapted from that question above:
// class.h
#include <iostream>
using namespace std;
template <typename T>
struct B
{
T value;
int value2;
B() : value2(1) {}
friend void modify(const int&); // unrelated to T!
void printValue2() {
modify(value2);
cout << value2 << endl;
}
};
// define friend function foo() in a class.cpp file, not in the header
void modify(const int &v) { v = v * 2 + 1; } // HOW should I write it?
// main.cpp
int main() {
B<int> b;
b.printValue2();
return 0;
}
I know I can declare modify() outside this template class so it becomes a vanilla, ordinary function. But I want only this template class to have access to modify(). Alternatively, to achieve this goal of access control, I could define modify() to be a static method in this template class, but that would make the method a template method, forcing me to define it in the header.
Followup: if the friend approach above doesn't work, how should I achieve the two goals at the same time:
access control: only that class template can access modify()
be able to define modify() in a *.cpp file, rather in a header.
Accepted Answer:
To achieve the two goals above, don't abuse friendship.
The best practice is let the class template privately inherit a non-template base class, and in that base class declare common non-template methods that are unrelated to template arguments.
Therefore, you are able to define these methods in a separate *.cpp file, reducing the header's size.
You might use private inheritance instead of friendship:
// class.h
#include <iostream>
class B_helper
{
protected:
static void modify(int &v);
};
template <typename T>
struct B : private B_helper
{
T value;
int value2;
B() : value2(1) {}
void printValue2() {
modify(value2);
std::cout << value2 << std::endl;
}
};
// class.cpp
void B_helper::modify(int &v) { v = v * 2 + 1; }
You do it like this:
// class.cpp
void modify(const int &v) { v = v * 2 + 1; }
You are effectively abusing friendship, but ok. What this means is that you need to work around what it means to declare a function with friend: It is only visible through ADL! Now there is no way to refer to modify, because modify doesn't depend on B, so B's scope is never searched for a function named modify.
There is a work-around, but it's not pretty. You need to declare modify in every function where you use it. You could also declare it in global scope, but then everyone can call it. Alternatively, you can always declare it in a detail namespace (but this has the same issue a bit):
template<typename T>
void B<T>::printValue2() {
void modify(const int&);
modify(value2);
cout << value2 << endl;
}
As I said in the comments, friendship controls access to a class. As long as your function modify() is a standalone function, it cannot be befriended. As you want to call it from a template, it cannot be hidden it in a .cpp file either, but must be visible with the definition of the class template B and its member using modify().
One solution is to put modify as a static method in a auxiliary non-template class, which in turn befriends the template B<>.
// file foo.h (header)
namespace foo {
template<typename> class B; // forward declaration
class exclusive_for_B
{
template<typename T>
friend class B<T>;
static void modify(int&x) // must take int&, not const int&
{ x &= x+42; }
};
template<typename T>
class B
{
int val;
public:
...
void printvalue()
{
exclusive_for_B::modify(val); // access via friendship
std::cout << val << '\n';
}
};
}

Templated classes with pimpl idiom incorrect

As described in the MSDN library here I wanted to experiment a bit with the pimpl idiom. Right now I have a Foo.hpp with
template<typename T>
class Foo {
public:
typedef std::shared_ptr<Foo<T>> Ptr;
Foo();
private:
class Impl;
std::unique_ptr<Impl> pImpl;
};
where the T parameter isn't used yet. The implementation is stored in Foo.cpp
template<typename T>
class Foo<T>::Impl {
public:
int m_TestVar;
};
template<typename T>
Foo<T>::Foo() : pImpl(new Impl) {
this->pImpl->m_TestVar = 0x3713;
}
Currently the compiler has two errors and one warning:
use of undefined type 'Foo<T>::Impl'; ... vc\include\memory in line 1150
can't delete an incomplete type; ... vc\include\memory in line 1151
deletion of pointer to incomplete type 'Foo<T>::Impl'; no destructor called; ... vc\include\memory in line 1152
What is the concflict here and how could I resolve it?
Edit. Removed the call to std::make_shared - copy&paste fail based on one old version.
I have had a similar issue - we've a base class in our system called NamedComponent and I wanted to create a template which takes an existing named component and converts it into a pimpl facade.
What I did was separate the template into a header and an inline file, and create a function to cause the template to be instantiated. This allows the implementation to be in a library, with the template instantiations of the facade with that implementation, and for the client to be able to use the facade based on the template and a forward declaration of the implementation.
header 'Foo.h':
template<class T> class Foo
{
public:
Foo ();
virtual ~Foo();
private:
T *impl_;
public:
// forwarding functions
void DoIt();
};
inline functions 'Foo.inl':
#include "Foo.h"
template<class T> Foo<T>::Foo() :
impl_ ( new T )
{
}
template<class T> Foo<T>::~Foo()
{
delete impl_;
}
// forwarding functions
template<class T> void Foo<T>::DoIt()
{
impl_ -> DoIt();
}
// force instantiation
template<typename T>
void InstantiateFoo()
{
Foo<T> foo;
foo.DoIt();
}
implementation cpp file - include the template inline functions, define the implementation, reference the instantiation function:
#include "Foo.inl"
class ParticularImpl {
public:
void DoIt() {
std::cout << __FUNCTION__ << std::endl;
}
};
void InstantiateParticularFoo() {
InstantiateFoo<ParticularImpl>();
}
client cpp file - include the template header, forward declare the implementation and use the pimpl facade:
#include "Foo.h"
class ParticularImpl;
int main () {
Foo<ParticularImpl> bar;
bar.DoIt();
}
You may have to fiddle with the InstantiateFoo function's contents to force the compiler to instantiate all functions - in my case, the base called all the pimpl's functions in template methods so once one was referenced, they all were. You don't need to call the Instantiate functions, just link to them.
IMHO PIMPL doesn't make much sense with templates, unless you know all possible template parameters and that set is fairly small. The problem is, that you will either have the Impl implementation in the header file otherwise, as has been noted in the comments. If the number of possible T parameters is small, you still can go with the separation, but you'll need to declare the specialisations in the header and then explicitly instantiate them in the source file.
Now to the compiler error: unique_ptr<Impl> requires the definition of Impl to be available. You'll need to directly use new and delete in the ctor Foo::Foo and dtor Foo::~Foo, respectively instead and drop the convenience/safety of smart pointers.

Inlining causes specialized member function of template class overriding virtual functions to get overlooked

I wanted to share a strange example with you guys that I stumbled upon and that kept me thinking for two days.
For this example to work you need:
triangle-shaped virtual inheritance (on member function getAsString())
member function specialization of a template class (here, Value<bool>::getAsString()) overriding the virtual function
(automatic) inlining by the compiler
You start with a template class that virtually inherits a common interface - i.e. a set of virtual functions. Later, we will specialize one of these virtual functions. Inlining may then cause our specilization to get overloooked.
// test1.cpp and test2.cpp
#include <string>
class ValueInterface_common
{
public:
virtual ~ValueInterface_common() {}
virtual const std::string getAsString() const=0;
};
template <class T>
class Value :
virtual public ValueInterface_common
{
public:
virtual ~Value() {}
const std::string getAsString() const;
};
template <class T>
inline const std::string Value<T>::getAsString() const
{
return std::string("other type");
}
Next, we have to inherit this Value class and the interface in a Parameter class that itself needs to be templated as well:
// test1.cpp
template <class T>
class Parameter :
virtual public Value<T>,
virtual public ValueInterface_common
{
public:
virtual ~Parameter() {}
const std::string getAsString() const;
};
template<typename T>
inline const std::string Parameter<T>::getAsString() const
{
return Value<T>::getAsString();
}
Now, do not(!) give the forward declaration of a specialization for Value for type equaling bool ...
// NOT in: test1.cpp
template <>
const std::string Value<bool>::getAsString() const;
But instead simply give its definition like this ...
// test2.cpp
template <>
const std::string Value<bool>::getAsString() const
{
return std::string("bool");
}
.. but in another module (that's important)!
And finally, we have a main() function to test what is happening:
// test1.cpp
#include <iostream>
int main(int argc, char **argv)
{
ValueInterface_common *paraminterface = new Parameter<bool>();
Parameter<int> paramint;
Value<int> valint;
Value<bool> valbool;
Parameter<bool> parambool;
std::cout << "paramint is " << paramint.getAsString() << std::endl;
std::cout << "parambool is " << parambool.getAsString() << std::endl;
std::cout << "valint is " << valint.getAsString() << std::endl;
std::cout << "valbool is " << valbool.getAsString() << std::endl;
std::cout << "parambool as PI is " << paraminterface->getAsString() << std::endl;
delete paraminterface;
return 0;
}
If you compile the code as follows (I placed it into two modules named test1.cpp and test2.cpp where the latter only contains the specialization and necessary declarations):
g++ -O3 -g test1.cpp test2.cpp -o test && ./test
The output is
paramint is other type
parambool is other type
valint is other type
valbool is bool
parambool as PI is other type
If you compile with -O0 or just -fno-inline - or also if you do give the forward declaration of the specialization - the result becomes:
paramint is other type
parambool is bool
valint is other type
valbool is bool
parambool as PI is bool
Funny, isn't it?
My explanation so far is: Inlining is at work in the first module (test.cpp). The required template functions get instantiated but some just end up being inlined in the calls to Parameter<bool>::getAsString(). On the other hand, for valbool this did not work but the template is instantiated and used as a function. The linker then finds both the instantiated template function and the specialized one given in the second module and decides for the latter.
What do you think of it?
do you consider this behavior a bug?
Why does inlining work for Parameter<bool>::getAsString() but not for Value<bool>::getAsString() although both override a virtual function?
I speculate that you have an ODR problem, so there is little sense in guessing why some compiler optimization behaves differently from another compiler setting.
In essence, the One Definition Rule states that the same entity should
have the exact same definition throughout an application, otherwise the
effects are undefined.
The fundamental problem is that the code that doesn't see the specialized version of your class template member function might still compile, is likely to link, and sometimes might even run. This is because in the absence of (a forward declaration of) the explicit specialization, the non-specialized version kicks in, likely implementing a generic functionality that works for your specialized type as well.
So if you are lucky, you get a compiler error about missing declarations/definitions, but if you are really unlucky you get "working" code that does not what you intend it to do.
The fix: always include (forward) declarations of all template specializations. It's best to put those in a single header and include that header from all clients that call your class for any possible template argument.
// my_template.hpp
#include "my_template_fwd.hpp"
#include "my_template_primary.hpp"
#include "my_template_spec_some_type.hpp"
// my_template_fwd.hpp
template<typename> class my_template; // forward declaration of the primary template
// my_template_primary.hpp
#include "my_template_fwd.hpp"
template<typename T> class my_template { /* full definition */ };
// my_template_spec_some_type.hpp
#include "my_template_fwd.hpp"
template<> class my_template<some_type> { /* full definition */ };
// some_client_module.hpp
#include "my_template.hpp" // no ODR possible, compiler will always see unique definition
Obviously, you could reorganize the naming by making subdirectories for template specializations and change the include paths accordingly.

Where to put a member function template

An aspect of C++ that periodically frustrates me is deciding where templates fit between header files (traditionally describing the interface) and implemention (.cpp) files. Templates often need to go in the header, exposing the implementation and sometimes pulling in extra headers which previously only needed to be included in the .cpp file. I encountered this problem yet again recently, and a simplified example of it is shown below.
#include <iostream> // for ~Counter() and countAndPrint()
class Counter
{
unsigned int count_;
public:
Counter() : count_(0) {}
virtual ~Counter();
template<class T>
void
countAndPrint(const T&a);
};
Counter::~Counter() {
std::cout << "total count=" << count_ << "\n";
}
template<class T>
void
Counter::countAndPrint(const T&a) {
++count_;
std::cout << "counted: "<< a << "\n";
}
// Simple example class to use with Counter::countAndPrint
class IntPair {
int a_;
int b_;
public:
IntPair(int a, int b) : a_(a), b_(b) {}
friend std::ostream &
operator<<(std::ostream &o, const IntPair &ip) {
return o << "(" << ip.a_ << "," << ip.b_ << ")";
}
};
int main() {
Counter ex;
int i = 5;
ex.countAndPrint(i);
double d=3.2;
ex.countAndPrint(d);
IntPair ip(2,4);
ex.countAndPrint(ip);
}
Note that I intend to use my actual class as a base class, hence the virtual destructor; I doubt it matters, but I've left it in Counter just in case. The resulting output from the above is
counted: 5
counted: 3.2
counted: (2,4)
total count=3
Now Counter's class declaration could all go in a header file (e.g., counter.h). I can put the implementation of the dtor, which requires iostream, into counter.cpp. But what to do for the member function template countAndPrint(), which also uses iostream? It's no use in counter.cpp since it needs to be instantiated outside of the compiled counter.o. But putting it in counter.h means that anything including counter.h also in turn includes iostream, which just seems wrong (and I accept that I may just have to get over this aversion). I could also put the template code into a separate file (counter.t?), but that would be a bit surprising to other users of the code. Lakos doesn't really go into this as much as I'd like, and the C++ FAQ doesn't go into best practice. So what I'm after is:
are there any alternatives for dividing the code to those I've suggested?
in practice, what works best?
A rule of thumb (the reason of which should be clear).
Private member templates should be defined in the .cpp file (unless they need to be callable by friends of your class template).
Non-private member templates should be defined in headers, unless they are explicitly instantiated.
You can often avoid having to include lots of headers by making names be dependent, thus delaying lookup and/or determination of their meaning. This way, you need the complete set of headers only at the point of instantiation. As an example
#include <iosfwd> // suffices
class Counter
{
unsigned int count_;
public:
Counter() : count_(0) {}
virtual ~Counter();
// in the .cpp file, this returns std::cout
std::ostream &getcout();
// makes a type artificially dependent
template<typename T, typename> struct ignore { typedef T type; };
template<class T>
void countAndPrint(const T&a) {
typename ignore<std::ostream, T>::type &cout = getcout();
cout << count_;
}
};
This is what I used for implementing a visitor pattern that uses CRTP. It looked like this initially
template<typename Derived>
struct Visitor {
Derived *getd() { return static_cast<Derived*>(this); }
void visit(Stmt *s) {
switch(s->getKind()) {
case IfStmtKind: {
getd()->visitStmt(static_cast<IfStmt*>(s));
break;
}
case WhileStmtKind: {
getd()->visitStmt(static_cast<WhileStmt*>(s));
break;
}
// ...
}
}
};
This will need the headers of all statement classes because of those static casts. So I have made the types be dependent, and then I only need forward declarations
template<typename T, typename> struct ignore { typedef T type; };
template<typename Derived>
struct Visitor {
Derived *getd() { return static_cast<Derived*>(this); }
void visit(Stmt *s) {
typename ignore<Stmt, Derived>::type *sd = s;
switch(s->getKind()) {
case IfStmtKind: {
getd()->visitStmt(static_cast<IfStmt*>(sd));
break;
}
case WhileStmtKind: {
getd()->visitStmt(static_cast<WhileStmt*>(sd));
break;
}
// ...
}
}
};
The Google Style Guide suggests putting the template code in a "counter-inl.h" file. If you want to be very careful about your includes, that might be the best way.
However, clients getting an included iostream header by "accident" is probably a small price to pay for having all your class's code in a single logical placeā€”at least if you only have a single member function template.
Practically your only options are to place all template code in a header, or to place template code in a .tcc file and include that file at the end of your header.
Also, if possible you should try to avoid #includeing <iostream> in headers, because this has a significant toll on compile-time. Headers are often #included by multiple implementation files, after all. The only code you need in your header is template and inline code. The destructor doesn't need to be in the header.