I have two template classes A and B in the same header file as follows:
template <typename T>
class FirstClass {
public:
bool convert(const FirstClass<T>& f){...}
bool convert(const SecondClass<T>& s){...}
};
template <typename T>
class SecondClass {
public:
bool convert(const FirstClass<T>& f){...}
bool convert(const SecondClass<T>& s){...}
};
In order to resolve any unknown class errors, I tried adding a forward declaration:
template <typename T> class SecondClass ; //adding this to the beginning of the file
I get the following error:
2 overloads have similar conversions
could be 'bool FirstClass<T>::convert(const FirstClass<T>& )'
or
could be 'bool FirstClass<T>::convert(const SecondClass<T>& )'
while trying to match the argument list '(FirstClass<T>)'
note: qualification adjustment (const/volatile) may be causing the ambiguity
I am assuming this is because I am using a forward declared class. Other than moving the implementation to Cpp files( which I have been told is cumbersome), is there any other efficient solution to this?
I am using VisualStudio 2010 on Windows 7
Just put the forward declarations before you define any of the two classes.
#include <iostream>
template<typename> class FirstClass;
template<typename> class SecondClass;
template <typename T>
class FirstClass {
public:
bool convert(const FirstClass<T>& f) { std::cout << "f2f\n"; }
bool convert(const SecondClass<T>& s){ std::cout << "f2s\n"; }
};
template <typename T>
class SecondClass {
public:
bool convert(const FirstClass<T>& f){ std::cout << "s2f\n"; }
bool convert(const SecondClass<T>& s){ std::cout << "s2s\n"; }
};
int main()
{
FirstClass<int> f;
SecondClass<int> s;
f.convert(f);
f.convert(s);
s.convert(f);
s.convert(s);
}
Output on Ideone
Related
I have a template class A<T> and its specialization for integral arguments. And both the class and its specialization declare the method foo(), which I would like to define outside of class bodies:
#include <concepts>
template<class T>
struct A { static void foo(); };
template<std::integral T>
struct A<T> { static void foo(); };
template<class T>
void A<T>::foo() {}
template<std::integral T>
void A<T>::foo() {}
int main() { A<int>::foo(); }
GCC accepts this code.
Clang prints the error https://gcc.godbolt.org/z/hYfYGPfMh :
error: type constraint differs in template redeclaration
template<std::integral T>
And MSVC prints errors on both method definitions:
error C3855: 'A<T>': template parameter 'T' is incompatible with the declaration
error C2447: '{': missing function header (old-style formal list?)
error C2065: 'foo': undeclared identifier
Please suggest how to define methods outside class bodies and make all the compilers happy?
I'm pretty sure that both the MS and Clang compilers are in error here and GCC is compiling your code correctly. Until these bugs are fixed in the other compilers, I suggest to continue using the concept pattern instead of going back to outdated methods. Simply work around the bug using an additional class:
#include <concepts>
#include <iostream>
// This is a work-around for using concept specialization of
// classes in conjunction with out-of-body definition of members.
// Only helpful for MSVC and Clang. GCC is properly compiling
// out-of-body concept specializations.
template <typename T>
class A
{
// For MSVC ONLY: the default template seems require being empty
// for this to work, but do fiddle around with it.
// (Also works with MSVC:)
A() = delete;
A(const A&) = delete;
A(A&&) noexcept = delete;
A& operator =(const A&) = delete;
A& operator =(A&&) noexcept = delete;
~A() = delete;
// Clang and GCC can have members just fine:
// static const char* foo();
};
// We use distinct base classes to define our concept specializations of A.
template <std::signed_integral T>
class A_Signed_Integral
{
public:
static const char* foo();
};
template <std::unsigned_integral T>
class A_Unsigned_Integral
{
public:
static const char* foo();
};
// And then we wrap them using the actual concept specializations of A,
// making the specializations effectivel the same class as the base class.
template <std::signed_integral T>
class A<T> :
public A_Signed_Integral<T>
{
public:
using A_Signed_Integral<T>::A_Signed_Integral; // grab all ctors
using A_Signed_Integral<T>::operator =; // an exceptional case
};
template <std::unsigned_integral T>
class A<T> :
public A_Unsigned_Integral<T>
{
public:
using A_Unsigned_Integral<T>::A_Unsigned_Integral;
using A_Unsigned_Integral<T>::operator =;
};
// Out-of-body definitions can be located to another file
template <std::signed_integral T>
inline const char* A_Signed_Integral<T>::foo()
{
return "using A<std::signed_integral T> foo";
}
template <std::unsigned_integral T>
inline const char* A_Unsigned_Integral<T>::foo()
{
return "using A<std::unsigned_integral T> foo";
}
int main()
{
std::cout << A<signed long>::foo() << std::endl;
std::cout << A<unsigned long>::foo() << std::endl;
return 0;
}
(Tested with all three compilers and works fine: see gcc.godbolt.org)
In the future, once the bugs are fixed it should be relatively easy with search and replace to erase the base classes in favor of just using the concept specializations of A.
EDIT:
Updating the example to work for MSVC, which cannot seem to make use of the default template yet.
I am not a C++ template expert, I tried something like below
template<class T, bool = std::is_integral_v<T>>
struct A
{};
template<class T>
struct A<T, false>
{
static void foo();
};
template<class T>
struct A<T, true>
{
static void foo();
};
template<class T>
void A<T,false>::foo()
{
std::cout << "I am working on a non-integral type" << std::endl;
}
template<class T>
void A<T, true>::foo()
{
std::cout << "I am working on an integral type" << std::endl;
}
int main()
{
A<int>::foo();
A<float> ::foo();
return 0;
}
and the code gave me the results on MS C++ compiler
I am working on an integral type
I am working on a non-integral type
I need to write a template in C++ that implements an abstract version of a set. I can't find a solution (or worse, don't really understand what to do) about a compile error.
This is a simplified version of the main program I need to compile and run -- that is, I MUST NOT change anything in this:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <set>
#include <string>
#include "testset.h"
using namespace std;
struct string_size_less
{
bool operator()( const std::string& a,
const std::string& b )
{
return a.size() < b.size();
}
};
int main()
{
std::set<std::string> msgs;
msgs.insert("One");
msgs.insert("Two");
msgs.insert("Three");
set_ops<std::string> ops(msgs);
ops.list();
std::set<std::string, string_size_less> x;
x.insert("Hello");
x.insert("Ciao");
std::set<std::string, std::greater<std::string> > a;
a.insert(":-o");
set_ops<std::string> m(x);
m.list();
return 0;
}
I need to write the 'set_ops' class (in testset.h). I stripped all the non-relevant parts (that otherwise work):
#pragma once
#include <iostream>
#include <set>
using namespace std;
template <class T> class set_ops
{
private:
std::set<T> elements;
public:
set_ops(std::set<T> initialSet)
{
elements = initialSet;
}
void list() const;
};
template <class T> void set_ops<T>::list() const
{
for (typename set<T>::iterator i = elements.begin(); i != elements.end(); ++i) {
cout << "\t" << *i << endl;
}
}
When I try to compile this, I get the error:
In function 'int main()':
error: no matching function for call to 'set_ops<std::__cxx11::basic_string<char> >::set_ops(std::set<std::__cxx11::basic_string<char>, string_size_less>&)'
note: candidate: set_ops<T>::set_ops(std::set<T>) [with T = std::__cxx11::basic_string<char>]|
note: no known conversion for argument 1 from 'std::set<std::__cxx11::basic_string<char>, string_size_less>' to 'std::set<std::__cxx11::basic_string<char> >'
I have tried many things and tried to find a good example, etc., but so far found none. I know for example (and tried it) that if I add another template parameter like this:
template <class T, class U = std::less<T> > class set_ops
{
private:
std::set<T, U> elements;
public:
set_ops(std::set<T, U> initialSet)
{
elements = initialSet;
}
void list() const;
};
template <class T, class U> void set_ops<T, U>::list() const
{
for (typename set<T, U>::iterator i = elements.begin(); i != elements.end(); ++i) {
cout << "\t" << *i << endl;
}
}
then if I explicitly write:
set_ops<std::string, string_size_less> m(x);
it compiles and runs without error. But, again, I MUST NOT change anything in main(), so that's not an option.
If I keep the line from the original main(), I get the same compile error even with the changes in testset.h.
I'd really like to understand the problem (and hopefully the solution) here, if anyone could help. Thanks!
This can be achieved through polymorphism and a template constructor.
#include <utility>
#include <memory>
#include <iostream>
template <typename T>
class set_ops
{
private:
// Interface type.
class set_ops_iface
{
public:
virtual ~set_ops_iface();
virtual void list() const = 0;
};
// Concrete implementation for a U.
template <typename U>
class set_ops_impl : public set_ops_iface
{
private:
U value;
public:
explicit set_ops_impl(U);
virtual void list() const override;
};
private:
// Smart pointer to interface type.
std::unique_ptr<set_ops_iface> impl;
public:
// Template constructor that can take any kind of container (not just sets)
template <typename U>
set_ops(U);
void list() const;
};
// Template constructor creates a set_ops_impl<U> owned by the interface smart pointer.
template <typename T>
template <typename U>
set_ops<T>::set_ops(U initial) :
impl{std::make_unique<set_ops_impl<U>>(std::move(initial))} { }
template <typename T>
set_ops<T>::set_ops_iface::~set_ops_iface() { }
template <typename T>
template <typename U>
set_ops<T>::set_ops_impl<U>::set_ops_impl(U initial) :
value{std::move(initial)} { }
// real list() implementation is in set_ops_impl<U>
template <typename T>
template <typename U>
void set_ops<T>::set_ops_impl<U>::list() const {
for (auto const & i : value) {
std::cout << '\t' << i << '\n';
}
}
// set_ops::list proxies to the polymorphic implementation.
template <typename T>
void set_ops<T>::list() const {
impl->list();
}
(Demo)
Note that, curiously, we don't even use the T template argument. set_ops wouldn't even need to be a template type if main() didn't require that it is.
To add another member function, you have to:
Add the implementation to the set_ops::set_ops_impl template.
Add a proxy member to set_ops.
The other answer works because std::function uses a technique called "type erasure". If you don't want to keep multiple std::functions, you can instead implement type erasure yourself.
template<typename T>
struct set_ops_erased {
virtual ~set_ops_erased() = default;
virtual void list() = 0;
};
template<typename T, typename Comp>
struct set_ops_impl : set_ops_erased<T> {
std::set<T, Comp> s;
set_ops_impl(std::set<T, Comp> s) : s(std::move(s)) { }
void list() override {
for(auto &x : s) std::cout << "\t" << x << "\n"; // endl is normally not necessary
}
};
template<typename T>
class set_ops {
std::unique_ptr<set_ops_erased<T>> ops;
public:
template<typename Comp>
set_ops(std::set<T, Comp> s)
: ops(std::make_unique<set_ops_impl<T, Comp>>(std::move(s)))
{ }
void list() { ops->list(); }
};
In this case, there's no need to worry about writing all the copy/move constructors/assignments and destructors. They just do the right thing. Because there is just one allocation of set_ops_impl, there's no need to think about using a "guarding" std::unique_ptr to clean up the container while the set_ops is being constructed.
Without changing main file, but forgetting initial order of given set (as you don't specify expected output), you might do:
template <class T> class set_ops
{
private:
std::set<T> elements;
public:
template <typename Container>
set_ops(Container& c) : elements(c.begin(), c.end()) {}
void list() const {
for (const auto& e : elements) {
std::cout << "\t" << e << std::endl;
}
}
};
I have a template API function in my class called template<typename T> T Get(/*stuff*/);. My source file implements this function for a certain list of T types. If the user wants to use a type that I have not implemented, then I want the result to be a compile error, and not a linker error. I don't care much about the compile message yet. Here's what I've got so far:
MyClass.h
#pragma once
#define API_TYPE(X) \
template<> struct Implemented<X> : public API<X> {}
namespace MyClassAPI
{
template<typename T> struct API
{
static T Get(const T&);
};
template<typename T> struct Implemented {};
API_TYPE(bool);
}
class MyClass
{
template<typename T> friend struct MyClassAPI::API;
public:
template<typename T> T Get(const T& t) const
{
return MyClassAPI::Implemented<T>::Get(t);
}
};
MyClass.cpp
#include "MyClass.h"
namespace MyClassAPI
{
template<typename T> T API<T>::Get(const T& t) { return t; }
//template struct API<bool> //Why do I need this?
}
main.cpp
#include "MyClass.h"
#include <iostream>
#include <cassert>
using namespace std;
// Main File
int main() {
MyClass c;
cout << "Getting true: " << c.Get(true) << endl;
return 0;
}
So my question is about a line in MyClass.cpp. Why do I need to replicate the API<bool> explicit declaration in the source file with template struct API<bool>;? Shouldn't it know to expand the template function definition from the header file's declaration when Implemented<bool> : public API<bool> inherits from it?
Also, is there a way to do this without declaring my accepted type list twice?
Error without the line:
g++ -Wfatal-errors -Werror -std=c++11 -g -O0 -Wall -c MyClass.cpp -o MyClass.o
g++ -Wfatal-errors -Werror -std=c++11 -g -O0 -Wall test.cpp MyClass.o -o test
/tmp/ccVxp4F3.o: In function `bool MyClass::Get<bool>(bool const&) const':
MyClass.h:25: undefined reference to `MyClassAPI::API<bool>::Get(bool const&)'
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
The problem with your template is you're defining it's members in a separate translation unit, hence they are not visible to main.cpp, and C++ does not support separate translation of templates.
When you use template struct API<bool>; you ask the compiler to explicitly instantiate API<T> for T = bool. However, when doing so, you should also let the other translations units know that the instantiation takes place elsewhere by having a similar directive in the header file with template declaration:
extern template struct API<bool>;
Otherwise, move the definition of Get to the header file or include .cpp file in the header file (not recommended) and rely on the compiler to instantiate template members for you.
As about limiting the list of viable template parameters, I suggest an approach based on template metaprogramming.
First we'll define some facility for checking whether a type belongs to a list of types, let's call it is_in<DesiredType, ViableTypes...>. It will accept as template parameters a type T to look for and a list of types InTypes... for search, and provide result by a static boolean member available at compile-time.
It is implemented as a simple recursive algorithm on a list, checking each element of the list against DesiredType until DesiredType is found or the end of list is met:
#include <type_traits>
template<typename...> struct is_in;
template<typename T, typename InType, typename... InTypes> struct is_in<T, InType, InTypes...> {
static constexpr bool value = std::is_same_t<T, InType> ||
is_in<T, InTypes...>::value;
}
template<typename T> struct is_in<T> {
static constexpr bool value = false;
}
Now, having is_in, we can just use static_assert and explicitly specify viable types for a template:
template<typename T> struct API
{
// Only allow API<bool> and API<int>
static_assert(is_in<T, bool, int>::value, "invalid template type for API<T>");
static T Get(const T&);
};
You almost have it there.
You need update MyClass.h to provide explicit instantiations of couple of functions and implement them in MyClass.cpp.
In the .h file, add:
// Explicit instantiations
namespace MyClassAPI
{
template<> int API<int>::Get(const int&);
template<> double API<double>::Get(const double&);
}
In the .cpp file, add:
// Implement the explicit instantiations
namespace MyClassAPI
{
template<> int API<int>::Get(const int& in)
{
// Add whatever logic that makes sense for this type.
return 2*in;
}
template<> double API<double>::Get(const double& in)
{
// Add whatever logic that makes sense for this type.
return 10*in;
}
}
Here's a single file version of working code:
#define API_TYPE(X) \
template<> struct Implemented<X> : public API<X> {}
namespace MyClassAPI
{
template<typename T> struct Implemented;
template<typename T> struct API
{
static T Get(T const&);
};
API_TYPE(int);
API_TYPE(double);
}
class MyClass
{
template<typename T> friend struct MyClassAPI::API;
public:
template<typename T> T Get(const T& t) const
{
return MyClassAPI::Implemented<T>::Get(t);
}
};
// Explicit instantiations
namespace MyClassAPI
{
template<> int API<int>::Get(const int&);
template<> double API<double>::Get(const double&);
}
#include <iostream>
int main()
{
MyClass a;
std::cout << a.Get<int>(10) << std::endl;
std::cout << a.Get<double>(10) << std::endl;
// Does not work. Produces compiler error.
// std::cout << a.Get<float>(10) << std::endl;
}
// Implement the explicit instantiations
namespace MyClassAPI
{
template<> int API<int>::Get(const int& in)
{
return 2*in;
}
template<> double API<double>::Get(const double& in)
{
return 10*in;
}
}
Output:
20
100
Update
Here'a multiple file version:
MyClass.h:
#pragma once
#define API_TYPE(X) \
template<> struct Implemented<X> : public API<X> {}
namespace MyClassAPI
{
template<typename T> struct Implemented;
template<typename T> struct API
{
static T Get(T const&);
};
API_TYPE(int);
API_TYPE(double);
}
class MyClass
{
template<typename T> friend struct MyClassAPI::API;
public:
template<typename T> T Get(const T& t) const
{
return MyClassAPI::Implemented<T>::Get(t);
}
};
// Explicit instantiations
namespace MyClassAPI
{
template<> int API<int>::Get(const int&);
template<> double API<double>::Get(const double&);
}
MyClass.cc:
#include "MyClass.h"
// Implement the explicit instantiations
namespace MyClassAPI
{
template<> int API<int>::Get(const int& in)
{
return 2*in;
}
template<> double API<double>::Get(const double& in)
{
return 10*in;
}
}
main.cc:
#include <iostream>
#include "MyClass.h"
int main()
{
MyClass a;
std::cout << a.Get<int>(10) << std::endl;
std::cout << a.Get<double>(10) << std::endl;
// Does not work.
// std::cout << a.Get<float>(10) << std::endl;
}
It also builds successfully and produces the same result.
If I have a class A
template <typename T>
class A { public: void print() const; };
I can write specific version of my methode print for specific template values my doing
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
and the calling the method print will just call the code of the good implementation (of the compiler tell me if I don't have an implementation for a specific template.
Now, if I have multiples types in my class B's template
template <typename T1, typename T2>
class B { public: void print() const; };
and if I try to do the same as before, let's say for T2
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
I get an compiler error :
error: invalid use of incomplete type 'class B<T1,bool>'
error: declaration of 'class B<T1, bool>'
What am I doing wrong ?
EDIT
My real life B class contains other methods with I do not want to specify (they work in the general case)
Having a partially specified class decalred makes that those generic methods aren't natively availlable
You can't partial specialize a function/method.
But you can partial specialize the whole class:
template <typename T1, typename T2> class B;
template<typename T1> class B<T1, bool>
{
public:
void print() const { printf("B w/ type bool\n"); }
};
What am I doing wrong?
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
These member functions are like normal functions, they are not templates with un-substituted parameters, so you are just providing definitions for the symbols, which will be used when those functions get called. (And like normal functions, if those definitions are in a header and you don't declare them inline you will get multiple definitions errors for them.)
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
This is not the same, this is providing a definition for a member function of a class template partial specialization. i.e. it's a template that will be used to generate code for the member of that partial specialization, but you haven't declared any such partial specialization, so you can't define its members.
You can make it compile by defining the partial specialization first:
// primary template
template <typename T1, typename T2>
class B { public: void print() const; };
// partial specialization
template<typename T1>
class B<T1,bool> { public: void print() const; };
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
However it is often inconvenient to have to repeat the entire class template definition just to define a partial specialization for one or two members, so it might be worth taking one of the alternative designs shown in other answers.
With templates it's best to decompose each part of the specialisation into its own template function or traits class.
Here's a clean way to do what you want:
template<typename T>
const char* type_name()
{
return "unknown";
};
template<>
const char* type_name<int>()
{
return "int";
}
template<>
const char* type_name<bool>()
{
return "bool";
}
struct foo {};
template<>
const char* type_name<foo>()
{
return "my custom foo";
}
struct bar {};
template <typename T>
class A {
public:
void print() const {
cout << "A w/ type " << type_name<T>() << '\n';
}
};
int main() {
A<bool> ab;
A<int> ai;
A<foo> af;
A<bar> abar;
ab.print();
ai.print();
af.print();
abar.print();
return 0;
}
output:
A w/ type bool
A w/ type int
A w/ type my custom foo
A w/ type unknown
Program ended with exit code: 0
With tag dispatching, you might do:
#include <iostream>
template<typename A, typename B>
class X
{
private:
template <typename U> struct Tag {};
template <typename U>
void print(Tag<U>) const;
void print(Tag<bool>) const { std::cout << "bool\n"; }
void print(Tag<int>) const{ std::cout << "int\n"; }
public:
void print() const { print(Tag<B>()); }
};
int main()
{
X<void, bool>().print();
X<void, int>().print();
}
I've got the following code (available also at http://ideone.com/6ozZrs):
#include <iostream>
template<class T>
class MyClass{
public:
inline MyClass(const T &t);
template<class C>
void MyUberFunction(const C &c)
{
std::cout<<"My t: "<<m_t<<std::endl;
std::cout<<"Do uber things with: "<<&c<<std::endl;
}
private:
T m_t;
};
template<class T>
MyClass<T>::MyClass(const T &t):
m_t(t)
{
}
int main(int argc, char *argv[])
{
MyClass<int> myInstance(1337);
myInstance.MyUberFunction("Another type");
return 0;
}
MyUberFunction method takes a different set of template parameters then its class. How can I split its declaration and definition (as I've done for class constructor)?
You can use this syntax for an out-of-class definition:
template<class T> // <== The class template parameters first
template<class C> // <== The member function template parameters after
void MyClass<T>::MyUberFunction(const C &c)
{
std::cout<<"My t: "<<m_t<<std::endl;
std::cout<<"Do uber things with: "<<&c<<std::endl;
}
Here is a live example of your modified code compiling.