Search code examples
c++visual-studio-2017return-valuelinker-errorsdeclval

Can I use declval to Construct an Unused Return?


Let's say I have a templatized function that is going to be specialized, so I really don't care about the base implementation. Can I do something like this:

template <typename T>
T dummy() {
    assert(false);
    return declval<T>();
}

When I try to do this in I get a linking error:

unresolved external symbol char const && __cdecl std::declval<char const >(void) (??$declval@$$CBD@std@@YA$$QEBDXZ) referenced in function char const __cdecl dummy<char const>()

Again this function is uncalled, but I do save a pointer to it. I can use return T{} instead, and that compiles, but I need this to work even if there isn't a default constructor for T. Is there a way that I can work around this?


Solution

  • You can work around the problem by not providing a definition for the function template. Using

    template <typename T>
    T dummy();
    
    template <>
    int dummy() { std::cout << "template <> int dummy()"; return 42;}
    
    int main()
    {
        dummy<int>();
        dummy<double>();
        return 0;
    }
    

    You will get a linker error because dummy<double>(); does not exist but if you comment it out then the code will compile because there does exist a specialization for int. This means you don't have to worry about returning anything.


    You can eve use

    template <typename T>
    T dummy() = delete;
    

    instead of not providing a definition so instead of getting a linker error you'll get a "nice" compiler error saying you are trying to use a deleted function. This also allows you to write overloads instead of specializations which is preferable as specializations are not considered during overload resolution. That's not really possible in your case since you don't take any parameters but if you do you should consider it.