Create a static class function that takes an infinite number of arguments

Hello! Using a template I've created a function that accepts an arbitary number of arguments. It's called classless_print and it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

template<typename First, typename... Strings>
void classless_print(First arg, const Strings &... rest) {
    std::cout << arg;
    classless_print(rest...);
}

void classless_print() {
    std::cout<<std::endl;
}

int main() {
    classless_print("Hello, World!","now for more stuff","huzzah!"); //--prints to console--> Hello, World!now for more stuff
    return 0;
}

My question is how do I encapsulate this function in class?

This is what I've tried:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
############ ducko.h############ 
#ifndef DUCKOUTILITIES_DUCKO_H
#define DUCKOUTILITIES_DUCKO_H

#include <iostream>

class ducko {
public:
    template <typename First, typename ... Strings>
    static void d_print(First arg, const Strings&... rest);
    static void d_print();
};


#endif //DUCKOUTILITIES_DUCKO_H
###############################

############ ducko.cpp############ 
#include "ducko.h"
template<typename First, typename... Strings>
void ducko::d_print(First arg, const Strings &... rest) {
    std::cout << arg;
    doSomething(rest...);
}

void ducko::d_print() {
    std::cout<<std::endl;
}
###############################
############# main.cpp ############
#include <iostream>
#include "ducko.h"
template<typename First, typename... Strings>
void classless_print(First arg, const Strings &... rest) {
    std::cout << arg;
    classless_print(rest...);
}

void classless_print() {
    std::cout<<std::endl;
}

int main() {
    classless_print("Hello, World!","now for more stuff","huzzah!"); //--prints to console--> Hello, World!now for more stuff
    ducko::d_print("trying to ", "encapsulate"); //--throws error--> LINK Pass 1: command "C:\PROGRA~2\MICROS~1\2017\COMMUN~1\VC\Tools\MSVC\1416~1.270\bin\Hostx86\x86\link.exe /nologo @CMakeFiles\duckoUtilities.dir\objects1.rsp /out:duckoUtilities.exe /implib:duckoUtilities.lib /pdb:C:\Users\jules\CLionProjects\duckoUtilities\cmake-build-debug\duckoUtilities.pdb /version:0.0 /machine:X86 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\duckoUtilities.dir/intermediate.manifest CMakeFiles\duckoUtilities.dir/manifest.res" failed (exit code 1120) with the following output:
    // main.cpp.obj : error LNK2019: unresolved external symbol "public: static void __cdecl ducko::d_print<char const *,char [12]>(char const *,char const (&)[12])" (??$d_print@PBD$$BY0M@D@ducko@@SAXPBDAAY0M@$$CBD@Z) referenced in function _main
    // duckoUtilities.exe : fatal error LNK1120: 1 unresolved externals
    return 0;
}


As you can see I get an error:
error LNK2019: unresolved external symbol

I'd love to put this function in a utility class and use it other projects! Thank you for your help
Last edited on
There's nothing special you need to do. Just put the definitions in the class body.
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <utility>

struct foo
{
  template <typename... Args> 
  static void print(Args&&... args) 
  { (std::cout << ... << std::forward<Args>(args)); }
};

int main() { foo::print("bar ", 24, ' ', 1.1); }  

Live demo:
http://coliru.stacked-crooked.com/a/b2d6aca25983cd0a

However, classes are not merely containers for names. Would a namespace be a better choice?
I'm a beginner so a namespace may indeed be better. Could I put your code in my ducko.cpp file?
Could I put your code in my ducko.cpp file?


No, you can't. Templates must be available to the compiler when their instantiations are compiled. Compiling a source file with just a template definition will not generate anything. Template code is NOT source code. When you compile the source that calls the template function, if the template is available (like in the header file), the function will be instantiated and will get compiled.

I also like to keep template definitions that look like source code in separate files. I write ".tcpp" files and place them there. Then I include the .tcpp file at the bottom of the .h file, so the template definitions are pulled in with the declarations. This style is ONLY FOR LOOKS. The simplest thing is to put the template definition into the header file and let it be.
Could I put your code in my ducko.cpp file?

Typically, templates must be defined in header files. See this post and the links it references:
http://www.cplusplus.com/forum/general/221822/#msg1018255

I'm a beginner so a namespace may indeed be better.

It's a design mistake to use a class only to group names. That's what namespaces are for.
Avoid writing member functions except when necessary. See:
https://web.archive.org/web/20190118203640/http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197
Last edited on
I am also a beginner . So, i just want to know about the given topic with some more explanation. Will you please help me? I just want to learn that how to Create a static class function that takes an infinite number of arguments.
Topic archived. No new replies allowed.