Somehow I am not able to understand this answer.
When a member function is defined outside class, why can't we have a simple nested name specifier (for example Foo::Foo(){} instead of having a more verbose Foo<T>::Foo(){}), even after the template declaration is repeated right before the member function definition.
The subtlety is that in
template<class T>
int VisitedSet::getSize() {
return vec.size();
}
the C++ compiler would not know yet what T applies to. When you're working inside the class definition for VisitedSet, you can use VisitedSet::... unambiguously, but outside the does not work.
When you're outside the class definition, the syntax requires that you tell the compiler what the template parameters are using the tempate<class T> syntax, and then that you tell the compiler where they apply.
In this case, that may seem ambiguous, but consider the following nested case:
template<class T>
class Foo {
template<class R>
class Bar {
int getSize();
};
};
Then it's more obvious why you need to be specific:
template<class X, class Y>
int Foo<Y>::Bar<X>::getSize() { ...
and
template<class A, class B>
int Foo<A>::Bar<B>::getSize() { ...
are both valid.
So that's why you need
template<class T>
int VisitedSet<T>::getSize() {
return vec.size();
}
even in the simpler case shown in the answer you link to.
Related
Consider this code:
struct A
{
template <typename T>
concept foo = true;
};
It doesn't compile. My Clang 10 gives me error: concept declarations may only appear in global or namespace scope, and GCC says something similar.
Is there a reason why it's not allowed? I don't see why it couldn't work, even if the enclosing class was a template.
The fundamental difficulty that would arise is that concepts could become dependent:
template<class T>
struct A {
template<T::Q X>
void f();
};
Is X a non-type template parameter of (dependent) type T::Q (which does not require typename in C++20), or is it a type template parameter constrained by the concept T::Q?
The rule is that it’s the former; we would need new syntax (along the lines of typename/template) to express the other possibility: perhaps something like
template<T::concept Q X> requires T::concept R<X*>
void A::g() {}
No one has explored such an extension seriously, and it could easily conflict with other extensions to concept syntax that might be more valuable.
The why is discussed in the answer by #DavisHerring. In this answer I want to share a pattern I was actually looking for when I encountered this question.
Depending on your use case, you maybe don't need the concept definition. If all you want to do is to avoid SFINAE trickery, you can directly invoke the requires clause and get rid of any concept at class scope:
struct A
{
template<typename T>
auto operator()(T t) const
{
if constexpr(requires { t.foo(); })
{
std::cout<<"foo"<<std::endl;
}
else
{
std::cout<<"no foo"<<std::endl;
}
}
};
and use that as
struct B { auto foo() {} };
struct C {};
int main()
{
A a;
a(B()); //prints "foo"
a(C()); //prints "no foo"
}
DEMO
However, if you find yourself using the same requires statement multiple times in your class, the original question why you just can't declare it once at class scope is justified.
Thus, in order to work around code duplication, you can declare a single static function which contains the concept you are looking for, e.g.
struct A
{
template<typename T>
static constexpr auto concept_foo(T t)
{
return requires{ t.foo(); };
}
template<typename T>
auto operator()(T t) const
{
if constexpr(concept_foo(t))
{
std::cout<<"foo"<<std::endl;
}
else
{
std::cout<<"no foo"<<std::endl;
}
}
};
This pattern could replace most use cases for concepts at class scope.
The title is a mouthful, but basically I wrote something like this:
enum EnumType{ValA, ValB};
template<EnumType> class A {};
template<>
class A<ValA>
{
private:
double param;
public:
A(double param);
};
template<>
A<ValA>::A(double param)
{
// Do Stuff
}
and when I try to compile it I get:
error: template-id 'A<>' for 'A<(EnumType)0u>::A(double)' does not
match any template declaration
Am I doing this wrong?
After searching online for similar cases, I tried to remove template<> (even though I don't understand why this would work), but then I get
multiple definition of 'A<(EnumType)0u>::A(double)'
I guess that I can replace template<> by inline (I tried and it compiles), but that doesn't feel like the proper way to do it (or if it is, I don't understand why).
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
Can someone explain to me what is wrong with what I wrote, why changing this seems to work, and what's the proper way to do it ?
The standard says:
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
Therefore, in your case you must use:
A<EnumType::ValA>::A(double param)
{
// Do Stuff
}
No template<> at all is just fine. That's because you are actually specializing a (special) member function (the constructor) of an explicitly specialized class template.
See it on coliru.
It would have been different if no explicit specialization was given.
As a minimal working example:
enum EnumType{ValA, ValB};
template<EnumType> class A
{
private:
double param;
public:
A(double param);
};
template<>
A<EnumType::ValA>::A(double)
{
// Do Stuff
}
int main() {
A<EnumType::ValA> a{0.};
}
In this case, template<> is required before the definition of the constructor because you are not defining a specialization of a member function of an already specialized class template.
You missed a semicolon (;) at the the end of class definition.
And the non template member function can be defined this way:
A<ValA>::A(double param) {
// Do Stuff
}
Informally, the template parameter list is only written when necessary, for example, for defining a member function template of a class template, the two template parameter list should all be written
template<class U, class V>
class A{
template <class T>
A();
};
template<class U, class V>
template <class T>
A<U, V>::A() {}
and a empty template parameter list is needed for a explicit specialisation of function template (which, i guess, is the reason why you use so here), informally because it tells the compiler that this is not a function overloading.
I realize similar questions have been asked before, but I read a couple of those and still don't see where I'm going wrong. When I simply write my class without separating the prototype from the definition, everything works fine. The problem happens when I separate the prototype and definition as shown below:
template<class T> class VisitedSet {
public:
VisitedSet();
int getSize();
void addSolution(const T& soln);
void evaluate();
private:
vector<T> vec;
int iteration;
};
And as an example of a definition that gives me this error:
int VisitedSet::getSize() {
return vec.size();
I've never made a templated class before, so please pardon me if the problem here is trivial.
VisitedSet is a template, not a class, so you can’t use VisitedSet in a nested name specifier such as VisitedSet::getSize(). Just as you specified the declaration of class VisitedSet<T> for all class T, you must specify the definition of VisitedSet<T>::getSize() for all class T:
template<class T>
int VisitedSet<T>::getSize() {
// ^^^
return vec.size();
}
The name of a template can, however, be used as though it were a class within a template definition:
template<class T>
struct Example {
Example* parent;
T x, y;
};
In this case, Example is short for Example<T>.
You want this:
template <class T>
int VisitedSet<T>::getSize() {
return vec.size();
}
You have to state the template parameter in the definition as well
template<class T>
int VisitedSet<T>::getSize() {
return vec.size();
}
otherwise the compiler cannot match it to the declaration. For example, there could be specializations for some parameter types.
You need to let your compiler know that you are implementing a method in template function:
template<typename T>
int VisitedSet<T>::getSize() {
return vec.size();
}
Try putting
template <typename T>
above the implementation of VisitedSet::getSize() -- but beware that, in general, templated classes and functions should all be inlined. See the c++ faq here for more information.
I've been facing a big challenge (for me, at least) regarding templates instancing and inheritance. Let's see this code:
class Convertible
{
public:
template<class T>
T* AsPtrTo()
{
return reinterpret_cast<T*>(this);
}
};
template<class T>
class TemplateBase : public Convertible
{
};
template<class T>
class TemplateDerived : public TemplateBase<T>
{
public:
void Method1(TemplateBase<T> t)
{
t.AsPtrTo<int>(); // <<<<<< ERROR
}
};
int main()
{
TemplateDerived<int> d;
TemplateBase<int> b;
d.Method1(b);
return 0;
}
As you can see, there is a class, called Convertible, with only one template method that performs a type casting. There is also a template class that inherits from Convertible, and then another template class that inherits from the previous one. This last template class implements a method that uses the template method AsPtrTo which should be inherited from Convertible and instanced during compilation for the type T, used in the main function.
For some reason I can't understand, this fails. GCC 4.4.1 gives me this message:
error: expected primary-expression before 'int'
I've marked the line of the error.
I thought maybe one of the C++ experts here could lend me a hand.
Thanks everybody in advance!
You need to use the keyword template as:
t.template AsPtrTo<int>();
This has been discussed so many times that you will find innumerable number of posts on SO.
But here you will find one of the best explanation:
Where and why do I have to put the "template" and "typename" keywords?
Try:
void Method1(TemplateBase<T> t)
{
t.template AsPtrTo<int>();
}
The reason is that the compiler doesn't know what member functions t has at parse time, so it doesn't know if AsPtrTo is a template function or not. Because of this, it can't parse it properly without the hint.
As an example for why this is needed, consider the following code:
struct Foo
{
template<int N> int foo(int x) { return x + N; }
};
struct Bar
{
int foo;
};
template <typename T>
int baz(T t)
{
return t.foo<0>(1);
}
At a glance, it looks like baz<Foo> would work, but baz<Bar> wouldn't, but it's the other way round!
Consider what happens if I call baz<Bar>
return t.foo<0>(1);
foo is a member variable, so when it sees the < it thinks it's a less-than operator, so it parses the expression like this:
return (t.foo < 0) > (1);
Which is a valid expression (after some implicit conversions to/from bool)!
The thing is, it parses the expression like that for both Foo and Bar, which is why the template keyword is needed. Compilers have to assume that it is not a template member function (unless you put that keyword there).
From the question:
Proper use of this->
The answer states that -> can be used
...in a template, in order to force the following symbol to be
dependent—in this latter use, it is often unavoidable.
What does this mean what what would a good example of this use be? I don't quite what "dependent" means in this context, but it sounds like a useful trick.
Posted in other question:
template <class T>
struct foo : T {
void bar() {
x = 5; // doesn't work
this->x = 5; // works - T has a member named x
}
};
Without this-> compiler doesn't know x is a (inherited) member.
Similar to use of typename and template inside template code:
template <class T, class S>
struct foo : T {
typedef T::ttype<S>; // doesn't work
typedef typename T::template ttype<S> footype; // works
};
It's silly and somewhat unnecessary, but you still gotta do it.
template <typename T>
struct Base
{
void foo() {}
};
template <typename T>
struct Derived : Base<T>
{
void bar()
{
// foo(); //foo() is a dependent name, should not call it like this
// Base<T>::foo(); //This is valid, but prevents dynamic dispatch if foo is virtual
this->foo(); //use of this-> forces foo to be evaluated as a dependent name
}
};
A more detailed explanation is available on the C++ FAQ
See Using this keyword in destructor [closed].
This is ugly, but this ugliness derives directly from the general name binding rules of "modern" templates (as opposed to macro-like template, as implemented by MS).