Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7176529
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 28, 20262026-05-28T16:31:36+00:00 2026-05-28T16:31:36+00:00

#include <QFile> #include <QString> // this is some sort of low-level C function void

  • 0
#include <QFile>
#include <QString>

// this is some sort of low-level C function
void lowLevelOpenFD(int fd)
{
    qDebug("Opened by fd: %d", fd);
}

// as well as this one
void lowLevelOpenName(const char *name)
{
    qDebug("Opened by name: %s", name);
}

// this is a wrapper around low-level functions
template<typename FileId>
void callLowLevelOpen(FileId id);

template<>
void callLowLevelOpen(const QString &fileName)
{
    lowLevelOpenName(QFile::encodeName(fileName).constData());
}

template<>
void callLowLevelOpen(int fd)
{
    lowLevelOpenFD(fd);
}

// this is the function where the most stuff happens
template<typename FileId>
void openInternal(FileId id)
{
    // lots of useful stuff goes here
    // now we call one of the two low level functions
    callLowLevelOpen(id);
    // more useful stuff
}

// this is high-level interface to the "open by name" function
void openFile()
{
    QString name = "file";
    openInternal(name);
}

// this is high-level interface to the "open by FD" function
void openFile(int fd)
{
    openInternal(fd);
}

int main()
{
    openFile();
    openFile(17);
    return 0;
}

The problem is that the example above results in

error LNK2019: unresolved external symbol "void __cdecl callLowLevelOpen<class QString>(class QString)" (??$callLowLevelOpen@VQString@@@@YAXVQString@@@Z) referenced in function "void __cdecl openInternal<class QString>(class QString)" (??$openInternal@VQString@@@@YAXVQString@@@Z)

As far as I can see it happens because the compiler instantiates openInternal<QString>() when it’s called from the first high-level overload. OK, so I thought and modified the code:

// this is high-level interface to the "open by name" function
void openFile()
{
    QString name = "file";
    openInternal<const QString&>(name);
}

The same problem. And I thought I told the compiler to instantiate the openInternal<const QString&>, so why it is still complains about <class QString>? I also tried this one:

// this is high-level interface to the "open by name" function
void openFile()
{
    QString name = "file";
    openInternal<const QString&>(static_cast<const QString&>(name));
}

Now this just looks silly and it still doesn’t work. I can’t explicitly specialize the openInternal() one because it’s too large and the very point of this templated mess is to avoid unnecessary code duplication. I can’t just rename the low level functions to turn them into overloaded ones, because they are in a third-party C library. The only thing I can do is to replace the first callLowLevelOpen() specialization with

template<>
void callLowLevelOpen(QString fileName)
{
    lowLevelOpenName(QFile::encodeName(fileName).constData());
}

Then it works. There is also virtually zero performance penalty so this is a perfectly valid workaround, but I just want to understand what is going on here.

The code above was just an SSCCE, the real code is there if anyone interested. This particular issue is with the gzopen()/gzdopen(), QuaGzipFilePrivate::open() and QuaGzipFile::open() functions.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-28T16:31:37+00:00Added an answer on May 28, 2026 at 4:31 pm

    Since you actually change the signature, I think you actually don’t want to specialize your function template but rather use overloading. Here is complete test program using std::string (I somehow prefer depending only on standard classes if the problem can be reproduced there as well):

    #include <string>
    
    template <typename T> void f(T);
    // #define BROKEN
    #if defined(BROKEN)
    template <> void f(std::string const&) {}
    #else
    void f(std::string const&) {}
    #endif
    
    int main()
    {
        std::string s;
        f(s);
    }
    

    If you #defined BROKEN in this code it won’t work.

    The reason for this behavior is that the compiler choose the overload based on the primary template. This will never add the const& part. Once this is done the compiler looks for potential specializations of the chosen overload. Since this will never have deduced the notation used for specialization this isn’t picked up.

    Why then is the f<std::string const&>(s) not picking up the specialization? For me it is, trying with both gcc and clang.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

#include<iostream> using namespace std; class A { int a; int b; public: void eat()
#include<iostream> class name { public: int a; name():a(0){}; }; void add(name * pname) {
#include <stdio.h> int main(void){ float a = 1.1; double b = 1.1; if(a ==
#include <stdio.h> void main() { int x=5,y=6; printf(%d%d%d,x++,(y=x++),(x=y++)); } Can anyone please explain why
#include <stdio.h> #include <stdlib.h> #include <time.h> #define length 100 void print_array(); int main() {
#include <iostream> using namespace std; int main (void) { cout << 1\t2\t3\t4\t5\t6\t7\t8\t9 << endl
#include<stdio.h> #include<conio.h> #define SQUARE(x) (x*x) void main() { clrscr(); int i=3,j,k; j=SQUARE(i++); k=SQUARE(++i); printf(\n%d\n%d\n%d,j,k,i);
#include <stdio.h> int main(void) { int i = 0; i = i++ + ++i;
#include<stdio.h> void f(void) { int s = 0; s++; if(s == 10) return; f();
#include <stdio.h> int main() { unsigned long long int num = 285212672; //FYI: fits

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.