0

I am trying to invoke a different hello_world function based on the value of the int x template parameter but same bye_world function for any template parameter of int x. Here is what was attempted (bool enable is used to try and achieve this):

// template_class.hpp
template <int x, int y, int z, bool enable> class TemplateClass { 
public: 
    void hello_world();
    void bye_world(); 
};
// template_class.cpp
#include <string>
#include <iostream>
using namespace std;
#include "template_class.hpp"

template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 1>::hello_world() { 
    std::cout << "hello world from 1" << endl; 
}

template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 2>::hello_world() { 
    std::cout << "hello world from 2" << endl; 
}

template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, enable>::bye_world() { 
    std::cout << "bye world either from 1 or 2" << endl;   
}

template class TemplateClass<1, 1, 1, true>; 
template class TemplateClass<2, 2, 2, true>; 
// main.cpp
#include <iostream> 
#include "template_class.hpp"
#include <string>

int main() { 
    TemplateClass<1, 1, 1, true> *a = new TemplateClass<1, 1, 1, true>(); 
    TemplateClass<2, 2, 2, true> *b = new TemplateClass<2, 2, 2, true>();
    a->hello_world(); 
    b->hello_world();
    b->bye_world(); 
    a->bye_world();
    return 0; 
}

compiler is not happy about this approach.

# g++ --std=c++11 main.cpp template_class.cpp -o run
template_class.cpp:6:82: error: nested name specifier 'TemplateClass<x, y, z, x == 1>::' for declaration does not refer into a class, class template or class template partial specialization
template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 1>::hello_world() { 
                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
template_class.cpp:10:82: error: nested name specifier 'TemplateClass<x, y, z, x == 2>::' for declaration does not refer into a class, class template or class template partial specialization
template <int x, int y, int z, bool enable> void TemplateClass<x, y, z, x == 2>::hello_world() { 
                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
2 errors generated.

Any ideas how to achieve this?

John Karasev
  • 151
  • 2
  • 11
  • 2
    You can only specialize the class in full, not its individual methods. Unless the method itself is a template, of course, but even then [it's not straightforward](https://stackoverflow.com/questions/5512910/explicit-specialization-of-template-class-member-function) – yeputons Dec 22 '22 at 01:32
  • 1
    And if you want to specialize for a specific value of `x`, then `x` shouldn't be present anymore in the specialization. Instead where `x` is passed as template argument should pass the value on which it is being specialized. `enable` is not required at all. – user17732522 Dec 22 '22 at 01:39
  • 2
    You could probably do a `constexpr` if statement here. – ChrisMM Dec 22 '22 at 01:39
  • Oh let me fix that... – John Karasev Dec 22 '22 at 01:44
  • Also, since it seems that your template should allow a number of different combinations of values as arguments, it seems unlikely that the two explicit instantiations for `TemplateClass<1, 1, 1, true>` and `TemplateClass<2, 2, 2, true>` are sufficient to cover all uses. I don't see a good reason here to use this approach instead of the usual implicit instantiation approach, placing the template member definitions into the `.hpp`. – user17732522 Dec 22 '22 at 01:45
  • @ChrisMM can you provide more detail of what you mean? – John Karasev Dec 22 '22 at 01:56
  • @yeputons most likely templating the method is what I am looking for. The end result is that there will be a list of TemplateClass implementations and within each one some methods are same as all of them while other methods are partially specialized and implemented for each different template parameter case. Are you able to provide more insight to your suggestion? – John Karasev Dec 22 '22 at 05:52

1 Answers1

0

Instead of doing this with the extra bool template parameters, you can just use an if constexpr statement in the function.

template <int x, int y, int z> void TemplateClass<x, y, z, x>::hello_world() { 
    if constexpr( x == 1 ) {
        std::cout << "hello world from 1" << std::endl; 
    } else { 
        std::cout << "hello world from 2" << std::endl; 
    }
}
ChrisMM
  • 8,448
  • 13
  • 29
  • 48
  • Ah, I see what you are saying. The reason why I am trying to get the templating way working is because this is a POC of a bigger use case that will introduce a messy list of if-else if they will be merged into one function. But will experiment, maybe will just end up using this approach. – John Karasev Dec 22 '22 at 05:44