Why do I get link errors when trying to create an instance of std::numpunct derivative?
I'm trying to make use of std::basic_stringstream<char16_t> with a UTF16-based std::numpunct. But an attempt to create even the simplest possible derivative of std::numpunct<char16_t> fails at link stage. Here's the code:
#include <locale>
struct my_punct : public std::numpunct<char16_t> {};
int main()
{
my_punct n;
}
And here are link errors (using g++ 7.2.0) (live test):
$ g++-7 test0.cpp -o test
/tmp/cc0oWPhL.o: In function `std::numpunct<char16_t>::numpunct(unsigned int)':
test0.cpp:(.text._ZNSt8numpunctIDsEC2Ej[_ZNSt8numpunctIDsEC5Ej]+0x36): undefined reference to `std::numpunct<char16_t>::_M_initialize_numpunct(__locale_struct*)'
/tmp/cc0oWPhL.o: In function `my_punct::~my_punct()':
test0.cpp:(.text._ZN8my_punctD2Ev[_ZN8my_punctD5Ev]+0x18): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0x8): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0xc): undefined reference to `std::numpunct<char16_t>::~numpunct()'
collect2: error: ld returned 1 exit status
If I change char16_t to char, linking completes successfully. So, what am I doing wrong here? Do I need some additional library to link against?
As a sanity check, I've tried grepping GCC installation for _ZTVSt8numpunctIDsE, and it gave no result. But grepping for _ZTVSt8numpunctIcE did find libstdc++.so.6.0.24. Does this mean I've found a bug in libstdc++?
c++ locale utf-16
add a comment |
I'm trying to make use of std::basic_stringstream<char16_t> with a UTF16-based std::numpunct. But an attempt to create even the simplest possible derivative of std::numpunct<char16_t> fails at link stage. Here's the code:
#include <locale>
struct my_punct : public std::numpunct<char16_t> {};
int main()
{
my_punct n;
}
And here are link errors (using g++ 7.2.0) (live test):
$ g++-7 test0.cpp -o test
/tmp/cc0oWPhL.o: In function `std::numpunct<char16_t>::numpunct(unsigned int)':
test0.cpp:(.text._ZNSt8numpunctIDsEC2Ej[_ZNSt8numpunctIDsEC5Ej]+0x36): undefined reference to `std::numpunct<char16_t>::_M_initialize_numpunct(__locale_struct*)'
/tmp/cc0oWPhL.o: In function `my_punct::~my_punct()':
test0.cpp:(.text._ZN8my_punctD2Ev[_ZN8my_punctD5Ev]+0x18): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0x8): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0xc): undefined reference to `std::numpunct<char16_t>::~numpunct()'
collect2: error: ld returned 1 exit status
If I change char16_t to char, linking completes successfully. So, what am I doing wrong here? Do I need some additional library to link against?
As a sanity check, I've tried grepping GCC installation for _ZTVSt8numpunctIDsE, and it gave no result. But grepping for _ZTVSt8numpunctIcE did find libstdc++.so.6.0.24. Does this mean I've found a bug in libstdc++?
c++ locale utf-16
2
It looks like the C++ library is only required to implement the template forcharandwchar_t. Forchar16_t, you're out of luck, and it's not supported by your C++ library.
– Sam Varshavchik
Dec 31 '18 at 20:42
@SamVarshavchik this would be better as an answer.
– Ruslan
Dec 31 '18 at 21:39
add a comment |
I'm trying to make use of std::basic_stringstream<char16_t> with a UTF16-based std::numpunct. But an attempt to create even the simplest possible derivative of std::numpunct<char16_t> fails at link stage. Here's the code:
#include <locale>
struct my_punct : public std::numpunct<char16_t> {};
int main()
{
my_punct n;
}
And here are link errors (using g++ 7.2.0) (live test):
$ g++-7 test0.cpp -o test
/tmp/cc0oWPhL.o: In function `std::numpunct<char16_t>::numpunct(unsigned int)':
test0.cpp:(.text._ZNSt8numpunctIDsEC2Ej[_ZNSt8numpunctIDsEC5Ej]+0x36): undefined reference to `std::numpunct<char16_t>::_M_initialize_numpunct(__locale_struct*)'
/tmp/cc0oWPhL.o: In function `my_punct::~my_punct()':
test0.cpp:(.text._ZN8my_punctD2Ev[_ZN8my_punctD5Ev]+0x18): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0x8): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0xc): undefined reference to `std::numpunct<char16_t>::~numpunct()'
collect2: error: ld returned 1 exit status
If I change char16_t to char, linking completes successfully. So, what am I doing wrong here? Do I need some additional library to link against?
As a sanity check, I've tried grepping GCC installation for _ZTVSt8numpunctIDsE, and it gave no result. But grepping for _ZTVSt8numpunctIcE did find libstdc++.so.6.0.24. Does this mean I've found a bug in libstdc++?
c++ locale utf-16
I'm trying to make use of std::basic_stringstream<char16_t> with a UTF16-based std::numpunct. But an attempt to create even the simplest possible derivative of std::numpunct<char16_t> fails at link stage. Here's the code:
#include <locale>
struct my_punct : public std::numpunct<char16_t> {};
int main()
{
my_punct n;
}
And here are link errors (using g++ 7.2.0) (live test):
$ g++-7 test0.cpp -o test
/tmp/cc0oWPhL.o: In function `std::numpunct<char16_t>::numpunct(unsigned int)':
test0.cpp:(.text._ZNSt8numpunctIDsEC2Ej[_ZNSt8numpunctIDsEC5Ej]+0x36): undefined reference to `std::numpunct<char16_t>::_M_initialize_numpunct(__locale_struct*)'
/tmp/cc0oWPhL.o: In function `my_punct::~my_punct()':
test0.cpp:(.text._ZN8my_punctD2Ev[_ZN8my_punctD5Ev]+0x18): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0x8): undefined reference to `std::numpunct<char16_t>::~numpunct()'
/tmp/cc0oWPhL.o:(.rodata._ZTVSt8numpunctIDsE[_ZTVSt8numpunctIDsE]+0xc): undefined reference to `std::numpunct<char16_t>::~numpunct()'
collect2: error: ld returned 1 exit status
If I change char16_t to char, linking completes successfully. So, what am I doing wrong here? Do I need some additional library to link against?
As a sanity check, I've tried grepping GCC installation for _ZTVSt8numpunctIDsE, and it gave no result. But grepping for _ZTVSt8numpunctIcE did find libstdc++.so.6.0.24. Does this mean I've found a bug in libstdc++?
c++ locale utf-16
c++ locale utf-16
asked Dec 31 '18 at 20:38
RuslanRuslan
5,80533373
5,80533373
2
It looks like the C++ library is only required to implement the template forcharandwchar_t. Forchar16_t, you're out of luck, and it's not supported by your C++ library.
– Sam Varshavchik
Dec 31 '18 at 20:42
@SamVarshavchik this would be better as an answer.
– Ruslan
Dec 31 '18 at 21:39
add a comment |
2
It looks like the C++ library is only required to implement the template forcharandwchar_t. Forchar16_t, you're out of luck, and it's not supported by your C++ library.
– Sam Varshavchik
Dec 31 '18 at 20:42
@SamVarshavchik this would be better as an answer.
– Ruslan
Dec 31 '18 at 21:39
2
2
It looks like the C++ library is only required to implement the template for
char and wchar_t. For char16_t, you're out of luck, and it's not supported by your C++ library.– Sam Varshavchik
Dec 31 '18 at 20:42
It looks like the C++ library is only required to implement the template for
char and wchar_t. For char16_t, you're out of luck, and it's not supported by your C++ library.– Sam Varshavchik
Dec 31 '18 at 20:42
@SamVarshavchik this would be better as an answer.
– Ruslan
Dec 31 '18 at 21:39
@SamVarshavchik this would be better as an answer.
– Ruslan
Dec 31 '18 at 21:39
add a comment |
1 Answer
1
active
oldest
votes
It's because there isn't a supporting implementation for the specialized class. What happens when you utilize a template is that the compiler generates a symbol for that particular use. If there is already a predefined and fully templated implementation, then the compiler can make its own definition, but only if it sees the templated implementation when it compiles the file trying to use it. If it can't see it, then it just creates the symbol, leaves it undefined, and expects to link it later.
As a quick example...
in Template_Add.h
// Generic template
template< class T >
T add(T first, T second);
in Template_Add.cpp
// Specialized for int
template<>
int add<int>(int first, int second){
in main.cpp
#include "Template_Add.h"
int main(){
int ia, ib, ic;
double da, db, dc;
ia = 3;
ib = 4;
da = 3.0;
db = 4.0;
// we expect ia = 7, and works
ic = add(ib, ic);
// we expect dc = 7.0, but doesn't work
// this will result in an unresolved symbol
dc = add(da, db);
return 0;
}
The reason for this behavior is that there isn't a templated implementation that exists anywhere where main.cpp can see it. When everything is linked, however, the linker sees that an "int add(int, int)" exists, and so that is allowed.
If you own the template, then you can add the (templated) implementation into the .h file containing the template declaration. That way the compiler knows how to generate the symbol and definition at compile time. To fix our above example, we could add the following code to Template_Add.h:
template< class T >
T add(T first, T second){
return first + second;
}
...and then anything including "Template_Add.h" would be able to generate its own implementation for anything trying to make use of the template.
If you don't own the template, then the best you can do is find a way to use the supported template specializations. In this case, it might be best to cast (or typedef) your char16_t into a short, and then see if that works.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53991243%2fwhy-do-i-get-link-errors-when-trying-to-create-an-instance-of-stdnumpunctchar%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
It's because there isn't a supporting implementation for the specialized class. What happens when you utilize a template is that the compiler generates a symbol for that particular use. If there is already a predefined and fully templated implementation, then the compiler can make its own definition, but only if it sees the templated implementation when it compiles the file trying to use it. If it can't see it, then it just creates the symbol, leaves it undefined, and expects to link it later.
As a quick example...
in Template_Add.h
// Generic template
template< class T >
T add(T first, T second);
in Template_Add.cpp
// Specialized for int
template<>
int add<int>(int first, int second){
in main.cpp
#include "Template_Add.h"
int main(){
int ia, ib, ic;
double da, db, dc;
ia = 3;
ib = 4;
da = 3.0;
db = 4.0;
// we expect ia = 7, and works
ic = add(ib, ic);
// we expect dc = 7.0, but doesn't work
// this will result in an unresolved symbol
dc = add(da, db);
return 0;
}
The reason for this behavior is that there isn't a templated implementation that exists anywhere where main.cpp can see it. When everything is linked, however, the linker sees that an "int add(int, int)" exists, and so that is allowed.
If you own the template, then you can add the (templated) implementation into the .h file containing the template declaration. That way the compiler knows how to generate the symbol and definition at compile time. To fix our above example, we could add the following code to Template_Add.h:
template< class T >
T add(T first, T second){
return first + second;
}
...and then anything including "Template_Add.h" would be able to generate its own implementation for anything trying to make use of the template.
If you don't own the template, then the best you can do is find a way to use the supported template specializations. In this case, it might be best to cast (or typedef) your char16_t into a short, and then see if that works.
add a comment |
It's because there isn't a supporting implementation for the specialized class. What happens when you utilize a template is that the compiler generates a symbol for that particular use. If there is already a predefined and fully templated implementation, then the compiler can make its own definition, but only if it sees the templated implementation when it compiles the file trying to use it. If it can't see it, then it just creates the symbol, leaves it undefined, and expects to link it later.
As a quick example...
in Template_Add.h
// Generic template
template< class T >
T add(T first, T second);
in Template_Add.cpp
// Specialized for int
template<>
int add<int>(int first, int second){
in main.cpp
#include "Template_Add.h"
int main(){
int ia, ib, ic;
double da, db, dc;
ia = 3;
ib = 4;
da = 3.0;
db = 4.0;
// we expect ia = 7, and works
ic = add(ib, ic);
// we expect dc = 7.0, but doesn't work
// this will result in an unresolved symbol
dc = add(da, db);
return 0;
}
The reason for this behavior is that there isn't a templated implementation that exists anywhere where main.cpp can see it. When everything is linked, however, the linker sees that an "int add(int, int)" exists, and so that is allowed.
If you own the template, then you can add the (templated) implementation into the .h file containing the template declaration. That way the compiler knows how to generate the symbol and definition at compile time. To fix our above example, we could add the following code to Template_Add.h:
template< class T >
T add(T first, T second){
return first + second;
}
...and then anything including "Template_Add.h" would be able to generate its own implementation for anything trying to make use of the template.
If you don't own the template, then the best you can do is find a way to use the supported template specializations. In this case, it might be best to cast (or typedef) your char16_t into a short, and then see if that works.
add a comment |
It's because there isn't a supporting implementation for the specialized class. What happens when you utilize a template is that the compiler generates a symbol for that particular use. If there is already a predefined and fully templated implementation, then the compiler can make its own definition, but only if it sees the templated implementation when it compiles the file trying to use it. If it can't see it, then it just creates the symbol, leaves it undefined, and expects to link it later.
As a quick example...
in Template_Add.h
// Generic template
template< class T >
T add(T first, T second);
in Template_Add.cpp
// Specialized for int
template<>
int add<int>(int first, int second){
in main.cpp
#include "Template_Add.h"
int main(){
int ia, ib, ic;
double da, db, dc;
ia = 3;
ib = 4;
da = 3.0;
db = 4.0;
// we expect ia = 7, and works
ic = add(ib, ic);
// we expect dc = 7.0, but doesn't work
// this will result in an unresolved symbol
dc = add(da, db);
return 0;
}
The reason for this behavior is that there isn't a templated implementation that exists anywhere where main.cpp can see it. When everything is linked, however, the linker sees that an "int add(int, int)" exists, and so that is allowed.
If you own the template, then you can add the (templated) implementation into the .h file containing the template declaration. That way the compiler knows how to generate the symbol and definition at compile time. To fix our above example, we could add the following code to Template_Add.h:
template< class T >
T add(T first, T second){
return first + second;
}
...and then anything including "Template_Add.h" would be able to generate its own implementation for anything trying to make use of the template.
If you don't own the template, then the best you can do is find a way to use the supported template specializations. In this case, it might be best to cast (or typedef) your char16_t into a short, and then see if that works.
It's because there isn't a supporting implementation for the specialized class. What happens when you utilize a template is that the compiler generates a symbol for that particular use. If there is already a predefined and fully templated implementation, then the compiler can make its own definition, but only if it sees the templated implementation when it compiles the file trying to use it. If it can't see it, then it just creates the symbol, leaves it undefined, and expects to link it later.
As a quick example...
in Template_Add.h
// Generic template
template< class T >
T add(T first, T second);
in Template_Add.cpp
// Specialized for int
template<>
int add<int>(int first, int second){
in main.cpp
#include "Template_Add.h"
int main(){
int ia, ib, ic;
double da, db, dc;
ia = 3;
ib = 4;
da = 3.0;
db = 4.0;
// we expect ia = 7, and works
ic = add(ib, ic);
// we expect dc = 7.0, but doesn't work
// this will result in an unresolved symbol
dc = add(da, db);
return 0;
}
The reason for this behavior is that there isn't a templated implementation that exists anywhere where main.cpp can see it. When everything is linked, however, the linker sees that an "int add(int, int)" exists, and so that is allowed.
If you own the template, then you can add the (templated) implementation into the .h file containing the template declaration. That way the compiler knows how to generate the symbol and definition at compile time. To fix our above example, we could add the following code to Template_Add.h:
template< class T >
T add(T first, T second){
return first + second;
}
...and then anything including "Template_Add.h" would be able to generate its own implementation for anything trying to make use of the template.
If you don't own the template, then the best you can do is find a way to use the supported template specializations. In this case, it might be best to cast (or typedef) your char16_t into a short, and then see if that works.
edited Dec 31 '18 at 21:25
answered Dec 31 '18 at 21:20
andrewecandrewec
898
898
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53991243%2fwhy-do-i-get-link-errors-when-trying-to-create-an-instance-of-stdnumpunctchar%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
It looks like the C++ library is only required to implement the template for
charandwchar_t. Forchar16_t, you're out of luck, and it's not supported by your C++ library.– Sam Varshavchik
Dec 31 '18 at 20:42
@SamVarshavchik this would be better as an answer.
– Ruslan
Dec 31 '18 at 21:39