0

I want to expose generic Timer. The problem is I don't know why extern got underlined with red and the Visual Studio 2019 Community says "linking specification is not allowed".

Question

What is the correct syntax for extern?

Minimal Working Example

The header utilities.hpp:

#pragma once

#ifdef UTILITIES_EXPORTS
#define UTILITIES_API __declspec(dllexport)
#else
#define UTILITIES_API __declspec(dllimport)
#endif

namespace Utilities
{   
    template<typename F>
    extern "C" UTILITIES_API void Timer(F f, unsigned int N = 1);
}

The definition file utilities.cpp:

#include "Timer.h"
#include <iostream>
#include <vector>
#include <chrono>
#include <iomanip>
using namespace std;

namespace Utilities 
{
    template<typename F>
    void Timer(F f, unsigned int N)
    {
        cout << fixed << setprecision(9);
        vector<unsigned int> results;
        const double million = 1'000'000'000.0;

        for (unsigned int i = 0; i < N; i++)
        {
            chrono::steady_clock::time_point begin = chrono::steady_clock::now();
            f();
            chrono::steady_clock::time_point end = chrono::steady_clock::now();

            unsigned int interval = chrono::duration_cast<chrono::nanoseconds>(end - begin).count();
            results.push_back(interval);
            double elapsedTime = interval / million;
            cout << "Elapsed: \t\t" << elapsedTime << " s." << endl;
        }

        unsigned long long sum = 0;
        for (unsigned int x : results)
            sum += x;
        double totalElapsedTime = sum / million / results.size();
        cout << "\t\t\tAverage elapsed: " << totalElapsedTime << " s." << endl;
    }
}
Second Person Shooter
  • 14,188
  • 21
  • 90
  • 165

1 Answers1

3

The compiler has to know what types you use with the generic, because it basically has to make a copy of Timer that works with that type.

For an extern method, there is no way to know this, and it would have to be evaluated at runtime, which is not how generics work. It's a compiler feature.

You can make a wrapper for a specific type and make that extern.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • I think I will use static library because using DLL is too complicated. – Second Person Shooter Apr 13 '19 at 05:23
  • 1
    @ArtificialHairlessArmpit The same applies to static library. Usually, templated code goes all in an hpp file. No cpp file. No compiled. Otherwise, don't use templates and declare a Timer for every type that it makes sense. – Mirko Apr 13 '19 at 05:56
  • @Mirko: Now I don't use both DLL and static library. Instead I just put the header and definition files in the same project. – Second Person Shooter Apr 13 '19 at 06:07
  • 1
    @ArtificialHairlessArmpit Aou are aware of [this](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file), are you? – πάντα ῥεῖ Apr 13 '19 at 07:49