After having found answers to many of my questions on stackoverflow, I have now come up against a question of which I can't find the answer and I hope that someone is willing to help me!
My problem is that I want to do an explicit templatization of a function inside a class in C++. My compiler (g++) and a look in the C++ standard (§14.7.3) tells me that this specialization has to be done in the namespace in which the class is declared. I understand that this implies that I cannot put the specialization inside the class, but I don't see the point of this restriction! Does anyone know if there is a good reason for not letting the specializations be made inside the class?
I know that there are workarounds, e.g. to put the function inside a struct, but I want to understand why the language has this design. If there is a good reason for not allowing specialized functions inside the class, I guess I should know it before trying to work around it.
Thanks in advance!
To make my question a little bit more precise: Here is some code from a test example which illustrates what I want to do:
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {
privateVariable = 5;
};
virtual ~SpecializationTest() {};
void execute() {
execute<DIMENSIONALITY>();
};
private:
int privateVariable;
template <size_t currentDim>
static void execute() {
printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
execute<currentDim-1>();
}
template <>
static void execute<0>() {
printf("This is the base case. Current dim is 0.\n");
}
};
This is not possible; g++ says:
SpecializationTest_fcn.h:27: error: explicit specialization in non-namespace scope ‘class MalinTester::SpecializationTest<DIMENSIONALITY>’
SpecializationTest_fcn.h:28: error: template-id ‘execute<0>’ in declaration of primary template
If I put the function execute outside the class, in the name space MalinTester, it will look like this:
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY> class SpecializationTest {};
template <size_t currentDim>
void execute() {
printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable);
execute<currentDim-1>();
}
template <>
void execute<0>() {
printf("This is the base case. Current dim is 0.\n");
}
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {};
virtual ~SpecializationTest() {};
void execute() {
MalinTester::execute<DIMENSIONALITY>();
};
private:
int privateVariable = 5;
};
};
};
and I cannot use privatevariable in the templatized versions of execute, as it is private in the class. I really want it private, as I want to have my data encapsulated as far as possible.
Of course I can send privateVariable as an argument to the function, but I think it would be more beautiful to avoid this, and what I really wonder is if there is a good reason for the C++ standard not to allow explicit specialization as in the first code example above.
#Arne Mertz: This is the workaround I have tried, but it doesn't allow using privateVariable either. And most of all, I wonder if it is a good idea to do like this. As I'm not allowed to make specializations of member functions, maybe I shouldn't do specializations of functions encapsulated in structs inside the class either.
#include <cstdio>
namespace MalinTester {
template <size_t DIMENSIONALITY>
class SpecializationTest {
public:
SpecializationTest() {
privateVariable = 5;
};
virtual ~SpecializationTest() {};
void execute() {
Loop<DIMENSIONALITY, 0>::execute();
};
private:
int privateVariable;
template <size_t currentDim, size_t DUMMY>
struct Loop {
static void execute() {
printf("This is the general case. Current dim is %d.\n", currentDim);
Loop<currentDim-1, 0>::execute();
}
};
template <size_t DUMMY>
struct Loop<0, DUMMY> {
static void execute() {
printf("This is the base case. Current dim is 0.\n");
}
};
};
};
Base specialization:
In .h:
template <class T>
class UISelectorSlider : public UISelectorFromRange<T> {
public:
UISelectorSlider();
virtual ~UISelectorSlider();
private:
float width;
float getPositionFromValue(T value);
};
In .cpp under same namespace:
template <>
float UISelectorSlider<MVHue>::getPositionFromValue(MVHue value)
{
return width * (float)value / 360.0;
}
If you want specialized function within specialized class:
Inside class add (.h) (private function):
private:
template <int I>
void foo();
Specialization inside .cpp:
template <>
template <>
void UISelectorSlider<MVHue>::foo<3>()
{
// you can access private fields here
}
UPDATE:
But you cant write something like this:
template <class T>
template <>
void UISelectorSlider<T>::foo<3>()
{
// you can access private fields here
}
You will get: error: enclosing class templates are not explicitly specialized.
It does not matter is this definition inside class or in namespace. The point is that this is not exact partial specialization - this function does not have defined context class (which members you want to call). In other words - when you specialize member you actually try specialize the whole containing class, but not the member itself. And compiler cant do that because class is not yet defined completely. So this is restriction by template design. And if it actually worked - templates would be full equivalent to simple macros.
(And you probably can will solve your task with some macro magic.)
Related
I've been struggeling with the following problem:
// this is in a header file
template <typename T>
struct Foo {
T x, y;
// ... other stuff
struct Bar {
int a, b;
// ... other stuff
void f() const;
};
Bar h() const
{ return { reinterpret_cast<int>(this->x), reinterpret_cast<int>(this->y) }; }
};
It's clear that Foo::h() needs to be implemented in the header file since it depends on the template argument.
But this is not the case for Foo::Bar::f().
I would like to implement this in a separate .cpp-file, since it only needs to compile once and so on.
Just as a note: I would like to keep this as a nested type for namespacing reasons.
Is there a nice way to do this ?
I dont't see why this shouldn't work, since Foo::Bar does not depend on the template argument at all.
Thank you very much !
Edit: fixed typo
I dont't see why this shouldn't work, since Foo::Bar does not depend on the template argument at all
This is not correct conclusion - the nested class has access to all names (private, protected, etc) to which the enclosing class has access, so depending on how the enclosing class is instantiated, the nested class has different surrounding context, thus Foo<int>::Bar and Foo<char>::Bar are not the same classes (to be precise - the nested class is part of the enclosing class definition, so without Foo<int>/Foo<char>, Bar doesn't exist, but since these are different classes, Bar under those classes are also different)
not sure what you mean by "namespacing reasons", but if you just want to access it like Foo<T>::Bar, you can use alias.
struct ChocolateBar {
int a, b;
// ... other stuff
void f() const;
};
template <typename T>
struct Foo {
T x, y;
// ...
using Bar = ::ChocolateBar;
Bar h() const { return { reinterpret_cast<int>(this->x), reinterpret_cast<int>(this->y) }; }
};
Hello template wizards,
I have been concocting a utility template which has one problem left to be solved, but cannot seem to figure it out. The code in this post is a simplification of the code in question, which exhibits the same issue.
Suppose you have a template specialisation as shown below.
enum class Pets { Dog, Cat, Bird };
template <Pets variant>
class Animal;
template <>
class Animal<Pets::Cat> {
void Sound();
};
template <>
class Animal<Pets::Dog> {
void Sound();
};
template <>
class Animal<Pets::Bird> {
void Sound();
};
void Animal<Pets::Cat>::Sound() { printf("Meow!\n"); }
void Animal<Pets::Dog>::Sound() { printf("Woof!\n"); }
void Animal<Pets::Bird>::Sound() { printf("Peep!\n"); }
And then I ruin everything by saying that I might not declare the specialisation of Animal<Pets::Bird>. The latter definition of ::Sound() will fail to compile, as the type doesn't exist. Now, this seems to beg for a SFINAE solution, to me, as we have an unwanted method implementation of a type that we don't want to exist.
I'd like the compiler to simply ignore that last method definition instead of failing compilation, without changing the method signature — that is, I don't want to make the method itself a template.
Do you have any suggestions on how to make this work?
You can’t do this: SFINAE is about overload resolution, and while it also supports the very similar case of selecting a partial specialization, it’s not a general conditional compilation technique. You can use the preprocessor, of course, and you can do tricks like declaring the unwanted function private so that it “doesn’t exist”, but you can’t define a function that just is never mentioned.
I did manage to conjure up a solution, which quite neatly just declares a catch-all, for those types are to be discarded — not quite what I asked for, but closer toward the goal.
This, at least, takes care of the definitions of methods that would otherwise fail compilation.
enum class Pets { Dog, Cat, Bird };
static constexpr Pets kChosenPet = Pets::Cat;
struct AbstractAnimal {
virtual void Sound() = 0;
};
template <Pets variant = kChosenPet, bool B = (variant == kChosenPet)>
struct Animal : public AbstractAnimal {
void Sound();
};
template <Pets variant>
struct Animal<variant, true> : public AbstractAnimal {
void Sound();
};
template <>
void Animal<Pets::Cat>::Sound() {
printf("Meow!\n");
}
template <>
void Animal<Pets::Dog>::Sound() {
printf("Woof!\n");
}
template <>
void Animal<Pets::Bird>::Sound() {
printf("Peep!\n");
}
May be I don't understand something in your question. But what's wrong with just moving declaration of Sound() to Animal?
#include <stdio.h>
#include <type_traits>
enum class Pets { Dog, Cat, Bird };
template <Pets variant>
class Animal {
void Sound();
};
template<>
void Animal<Pets::Cat>::Sound() { printf("Meow!\n"); }
template<>
void Animal<Pets::Dog>::Sound() { printf("Woof!\n"); }
template<>
void Animal<Pets::Bird>::Sound() { printf("Peep!\n"); }
"SFINAE" means "Substitution Failure Is Not An Error". That starts with "Subsitution", an early part of the template instantiation process. And SFINAE is only Not An Error when there are alternatives for the failed template, e.g. other function overloads.
Now in void Animal<Pets::Bird>::Sound(), there is no Substitution, so SFINAE can't apply. We can't introduce it either - the normal way is via std::enable_if, which can turn a non-template declaration into a template declaration that might or might not be instantiated. But that doesn't work - this specialization cannot be a template declaration.
This case can be simplified:
#ifdef FOO
class Foo { int bar; }
#endif
int Foo::bar() { return 1; } // Also not fixable by SFINAE, for the same reason.
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';
}
};
}
I'm designing a wrapper over various computational functionality. Some of the underlying backends require some init functions to be called before any other API calls are made. I could use some static variable that is initialized before main, and wrap it in some function as described here so that I can catch any errors produced during initialization.
I wonder if there is a better way to handle this. Note that there will never be an instance of the class template, as everything is either a typedef or static member.
To address the problem of initializing the API only for some specializations, and of initializing it only once, I'd do something like this:
#include <iostream>
template <typename T>
struct Wrapper
{
// class who will be statically instantiated
struct CtorClass
{
CtorClass()
{
std::cout << "Init\n";
}
};
static CtorClass static_ctor;
static void compute1(){}
static void compute2(){}
};
// definition for template static member cons
template <typename T>
typename Wrapper<T>::CtorClass Wrapper<T>::static_ctor;
struct NeedInit{};
// you will have to use static_ctor in every funcition of the
template <>
void Wrapper<NeedInit>::compute1()
{
static_ctor;
}
template <>
void Wrapper<NeedInit>::compute2()
{
static_ctor;
}
int main()
{
Wrapper<int>::compute1();
Wrapper<int>::compute2();
Wrapper<NeedInit>::compute1();
Wrapper<NeedInit>::compute2();
}
Sadly, this way you have to use static_ctor in every function specialization that belongs to a Wrapper<NeedInit> class. But you wouldn't need to check for the initialization to have already been called.
Then, you could catch errors like you said.
I hav a following piece of code in a module.
Controller is the name of the class.
allocate_route is the member function of it.
While defining the member function it is given as
template<UI num_ip>
void Controller<num_ip>::allocate_route()
{
}
UI is Unsigned Integer. num_ip is not defined any where. He also has not used num_ip anywhere inside the code. What does he tell to the compiler by this statement. Am not able to comprehend the use of templates here. Wat does this code do?
That code implements the function allocate_route defined in the template class Controller.
When creating template classes, you have two way to implement functions:
template <int a>
class A
{
void x() { ... }
};
or
template <int a>
class A
{
void x();
};
template <int a>
void A<a>::x()
{
}
Maybe he is using num_ip somewhere outside this method, but still inside Controller class (maybe another method).
If you define method inside a template you have to add template<...>, even if method doesn't use template parameters. That's why it could be better to do something like this in this case:
class Controller_base
{
void allocate_route(){
}
};
template<UI num_ip>
class Controller: public Controller_base
{
}
void Controller_base::allocate_route()
{
}