Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Compiling C++ non-type template parameters outside headers?

This may be a silly question, but I have been struggling with this problem, and ChatGPT solutions aren’t able to solve it.

I have the following class definition:

template<typename U, typename = std::enable_if_t<std::is_base_of_v<int, U>>>
class TestClass {
  public:
    auto print() -> void;
};

If I implement print() within the declaration / header itself, this is trivial:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> = 0>
class TestClass
{
    auto print()
    {
       std::cout << "Hello";
    }
};

However, if I try to move this into a cpp file for it’s implementation, I cannot get it to compile. Here is one of my attempts:

template<typename U, typename>
void TestClass<U, std::enable_if_t<std::is_base_of_v<int, U>>>::print()
{
    std::cout << "Printing from TestClass" << std::endl;
}

And here is that attempt’s compilation error:

main.cpp:14:19: error: template argument for non-type template parameter must be an expression
void TestClass<U, std::enable_if_t<std::is_base_of_v<int, U>>>::print()
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:6:71: note: template parameter is declared here
template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> = 0>
                                                                      ^
1 error generated.

What is the correct syntax when moving this into a cpp file?

>Solution :

The common way of doing this(syntax-wise) is to specify the default argument in the first occurrence of the definition/declaration and ommit it in the next as shown below.

This means that there are two ways to solve this depending upon which of the two code snippets given in your question you’re using.

Method 1

//specify default argument here
template<typename U, typename = std::enable_if_t<std::is_base_of_v<int, U>>>
class TestClass {
  public:
    auto print() -> void;
};
//no default argument here
template<typename U, typename N>
void TestClass<U, N>::print() 
{
       std::cout << "Hello"; 
}

working demo

Method 2

//specify the default argument here
template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> = 0>
class TestClass
{
    auto print() -> void;
    
};
//no need to specify default argument here
template<typename U, std::enable_if_t<std::is_base_of_v<U, int>, int> N>
void TestClass<U, N>::print()
{
       std::cout << "Hello";
}

Working demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading