I cannot compile my program with VS2015 due to a function using a templated parameter and inheritance.
The error is this one.
I'm trying to achieve the following :
class A
{
//do something
};
class B : public A
{
//do something
};
template <typename T>
class Foo {
template <typename T>
friend void function(Foo<T> & sm) {
//do something
}
};
void main()
{
Foo<A> test;
Foo<B> test2;
};
I do understand the meaning of the error, but I do not understand why it actually happens.
I suppose function is created with two different signatures :
void function(Foo<A> & sm); and
void function(Foo<B> & sm);
How is that a multi-definition?
EDIT - The full error message :
Error C2995 'void function(Foo<T> &)': function template has already been defined
EDIT² - From scratch
Both Clang and MS have the same complaint. Remove the second template specifier and it will compile.
class A{};
class B : public A{};
template <typename T>
class Foo {
// template <typename T>
friend void function(Foo<T> & sm) {
}
};
int main()
{
Foo<A> test;
Foo<B> test2;
};
T is already specified for the class Foo so its friend function is covered. You would us a second template if there were a difference at the function, like:
class A{};
class B : public A{};
template <typename T>
class Foo {
template <typename U>
friend void function(Foo<T> & sm, U another) {
}
};
int main()
{
Foo<A> test;
Foo<B> test2;
};
Related
In my serialization system, I can provide non-member functions that implement how to serialize given types:
// struct foo
struct foo {
int bar;
};
// serialize foo
template <class stream> void serialize(stream& s, foo& f) {
stream.serialize(f.bar);
}
If I wanted to provide an empty serialize implementation when a non-member function serialize does not exist for a given type, how can I achieve that using C++11?
I tried this
template <class stream, class type> void serialize(stream&, type&) {}
// struct foo
struct foo {
int bar;
};
// serialize foo
template <class stream> void serialize(stream& s, foo& f) {
stream.serialize(f.bar);
}
// ...later in source file:
foo f;
stream s;
serialize(s, f);
but it always calls the empty method somehow.
Add a non-member function template.
template <typename stream, typename T> void serialize(stream& s, T& t) {}
Here's a demonstrative program:
#include <iostream>
template <typename stream, typename type> void serialize(stream&, type&)
{
std::cout << "Came to 1\n";
}
struct stream
{
void serialize(int ) {}
};
// struct foo
struct foo {
int bar;
};
// serialize foo
template <class stream> void serialize(stream& s, foo& f) {
std::cout << "Came to 2\n";
s.serialize(f.bar);
}
struct bar {
};
int main()
{
// ...later in source file:
foo f;
stream s;
serialize(s, f);
bar b;
serialize(s, b);
}
and its output under cygwin/g++ 6.4.0:
Came to 2
Came to 1
It works at ideone.com too.
I'm just starting my journey into more advanced template code. Consider the following...
template <typename T>
class node_base
{
public:
T member;
node_base() {}
void do_the_thing(node_base& other)
{
std::cout << other.member;
}
};
template <typename ...Args>
class node : public node_base<Args>...
{
public:
node() :node_base<Args>()...{}
};
int main()
{
node<int> int_node;
node<int, double> double_node;
int_node.do_the_thing(double_node);
double_node.do_the_thing(int_node); // ambiguous call
std::cin.ignore();
return 0;
}
Using Visual Studio 2017 15.4.5, I get the following...
error C2385: ambiguous access of 'do_the_thing' note: could be the
'do_the_thing' in base 'node_base' note: or could be the
'do_the_thing' in base 'node_base'
My understanding is that the compiler should be able to deduce the correct function based on the argument, in this case node<int>. Why is this call considered ambiguous? What can I do to clarify the call while still maintaining this template pattern?
It's not about templates. You can reproduce it with the following:
struct A1 { void foo(); };
struct A2 { void foo(); };
struct B : A1, A2 {};
int main()
{
B b;
b.foo();
}
The relevant part of the Standard is
If the resulting set of declarations are not all from sub-objects of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is an ambiguity and the program is ill-formed.
So, you have two subobjects of types node_base<int> and node_base<double>.
EDIT: To address changes in the question and as DeanSeo deleted his solution, i will post it here:
template <typename T>
class node_base
{
public:
T member = sizeof(T);
node_base() {}
void do_the_thing(node_base& other) {
std::cout << other.member << std::endl;
}
};
template <typename ...Args>
class node : public node_base<Args>...
{
public:
node() :node_base<Args>()...{}
template <class T>
void do_the_thing(node_base<T>& other) {
node_base<T>::do_the_thing(other);
}
};
int main()
{
node<int> int_node;
node<double, int> double_node;
int_node.do_the_thing<int>(double_node);
double_node.do_the_thing(int_node);
double_node.do_the_thing<double>(double_node);
double_node.do_the_thing<int>(double_node);
return 0;
}
This question already has answers here:
Templated check for the existence of a class member function?
(33 answers)
Closed 6 years ago.
1) I have two classes class A and class B which both have a method called foo but with different argument lists.
class A {
public:
void foo(int a);
};
class B {
public:
void foo(int a, int b);
};
2) Further, I have a class C with template argument T that also has a foo method as following
template <typename T>
class C {
public:
void foo();
private:
T t_;
int a_;
int b_;
};
3) I would like use both class A and class B as template argument for class C.
Saying that I would like to have a method C::foo to be implemented like following:
template <typename T>
void C<T>::foo()
{
if (compile time check: T has foo(int a, int b))
t_.foo(a_, b_);
else
t_.foo(a_);
}
How can I express the if statement above in C++11?
Use SFINAE (with function template overloading).
template <typename T>
class C {
private:
T t_;
int a_;
int b_;
public:
template <typename X = T>
auto foo() -> decltype (std::declval<X>().foo(a_)) {
t_.foo(a_);
}
template <typename X = T>
auto foo() -> decltype (std::declval<X>().foo(a_, b_)) {
t_.foo(a_, b_);
}
};
LIVE
If you know which type contains void foo(int a, int b); which in this case you do, you can use template specialization, something like
template <typename T>
class C
{
private:
T t_;
int a_;
int b_;
public:
// called for general use
void foo()
{
t_.foo(a_);
}
};
// specialized version for T = B
template<>
void C<B>::foo()
{
t_.foo(a_, b_);
}
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 have a small problem that is killing me!! I don't know what seems to be wrong with the below code. I should be able to implement the function that is inherited from the super class, shouldn't I? but I get error: out-of-line definition of 'test' does not match any declaration in 'B<dim>'
template <int dim>
class A
{
public:
virtual double test() const ;
};
template <int dim>
class B : public A <dim>
{
};
template <int dim>
double B<dim>::test () const
{
return 0;
}
I am on a Mac using clang (Apple LLVM version 5.1).
Try
template <int dim>
class B : public A <dim>
{
public:
virtual double test () const;
};
// Function definition
template <int dim>
double B<dim>::test () const
{
return 0;
}
You still need to define the function declared the class declaration.
The problem is that you are trying to define function test outside the class definition of class B. You have to declare it at first in the class
template <int dim>
class B : public A <dim>
{
double test() const;
};