ryan0270 ryan0270 - 3 months ago 11
C++ Question

c++ function to return "zero" of the appropriate type

I'm trying to write a zero() template function that will always return zero of the appropriate type. This is trivial for base types but I'd like similar behavior for user-defined types (which could provide their own overload). For example

auto i = zero<int>() // i is an in
auto d = zero<double>() // d is a double
auto m = zero<Matrix2d>() // m is a Matrix2d with all elements initialized to zero.


What I have is this:

template <typename T>
T zero() {
return T{}*0; // Clearly not correct for all types, but known incorrect cases should be specialized
}

template <>
int zero<int>() { return 1; } // intentionally wrong for testing


but calling

cout << zero<int>() << endl;


is outputting 0 indicating the specialization is not being called. What am I doing wrong?

*NOTE: The use case is similar to std::accumulate, but imagine the starting value is always zero and we don't want to require the user to pass that in.

UPDATE
As a couple commentors noted, this works in Ideone. Something about my specific implementation is breaking it then. I have:

zero.h:

template <typename T>
constexpr T zero() {
return T{}*0;
}


zero.cpp:

#include "zero.h"
template <>
constexpr int zero<int>() { return 1; }


main.cpp:

#include <iostream>
#include "zero.h"

using namespace std;
int main(int argc, char **argv) {
cout << "int: " << zero<int>() << endl;
}

Answer

Avoid using templates in ".cpp" files. Some useful references.

Try to move everything into the header file:

zero.h:

template <typename T>
T zero() {
    return T{}*0;
}

template <>
int zero<int>() { return 1; }

And delete the file zero.cpp.

EDIT:

If you're using Visual Studio, this could be useful:

This error will also be generated as a result of compiler conformance work that was done in Visual Studio .NET 2003:. For code will be valid in the Visual Studio .NET 2003 and Visual Studio .NET versions of Visual C++, remove template <>.