How do write template function that can get a substring of a QString or a std::string?












0















I'd like to write a template function that can handle both QString and std::string in order to reduce copied code. Unfortunately, QString does not implement the substr member function. QString::mid(int, int) seems to be the Qt analogue. What is the best way to handle this discrepancy? Below is the function I have that should act on std::string-like objects:



Template function:



template <typename StringType>
void do_something(StringType s, StringType::size_type start, StringType::size_type length) {
// Not defined if StringType == QString
StringType sub_s = s.substr(start, length);

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


My guess is that I will need to create another function get_substr that is defined for both std::string and QString, which I can call in do_something, but I am not sure if this is the ideal solution.










share|improve this question




















  • 5





    Traits/Policy or simple overload seems fine to handle the difference part.

    – Jarod42
    Dec 31 '18 at 23:22








  • 1





    QString has begin() and end() members, so any range algorithm should work equally.

    – zett42
    Dec 31 '18 at 23:48











  • user zett42 has given an excellent and valid solution, however my answer provides an alternative approach that uses QString's toStdString() member function. Thought I'd just provide you with another working solution as it would increase your available toolset.

    – Francis Cugler
    Jan 2 at 1:14
















0















I'd like to write a template function that can handle both QString and std::string in order to reduce copied code. Unfortunately, QString does not implement the substr member function. QString::mid(int, int) seems to be the Qt analogue. What is the best way to handle this discrepancy? Below is the function I have that should act on std::string-like objects:



Template function:



template <typename StringType>
void do_something(StringType s, StringType::size_type start, StringType::size_type length) {
// Not defined if StringType == QString
StringType sub_s = s.substr(start, length);

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


My guess is that I will need to create another function get_substr that is defined for both std::string and QString, which I can call in do_something, but I am not sure if this is the ideal solution.










share|improve this question




















  • 5





    Traits/Policy or simple overload seems fine to handle the difference part.

    – Jarod42
    Dec 31 '18 at 23:22








  • 1





    QString has begin() and end() members, so any range algorithm should work equally.

    – zett42
    Dec 31 '18 at 23:48











  • user zett42 has given an excellent and valid solution, however my answer provides an alternative approach that uses QString's toStdString() member function. Thought I'd just provide you with another working solution as it would increase your available toolset.

    – Francis Cugler
    Jan 2 at 1:14














0












0








0








I'd like to write a template function that can handle both QString and std::string in order to reduce copied code. Unfortunately, QString does not implement the substr member function. QString::mid(int, int) seems to be the Qt analogue. What is the best way to handle this discrepancy? Below is the function I have that should act on std::string-like objects:



Template function:



template <typename StringType>
void do_something(StringType s, StringType::size_type start, StringType::size_type length) {
// Not defined if StringType == QString
StringType sub_s = s.substr(start, length);

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


My guess is that I will need to create another function get_substr that is defined for both std::string and QString, which I can call in do_something, but I am not sure if this is the ideal solution.










share|improve this question
















I'd like to write a template function that can handle both QString and std::string in order to reduce copied code. Unfortunately, QString does not implement the substr member function. QString::mid(int, int) seems to be the Qt analogue. What is the best way to handle this discrepancy? Below is the function I have that should act on std::string-like objects:



Template function:



template <typename StringType>
void do_something(StringType s, StringType::size_type start, StringType::size_type length) {
// Not defined if StringType == QString
StringType sub_s = s.substr(start, length);

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


My guess is that I will need to create another function get_substr that is defined for both std::string and QString, which I can call in do_something, but I am not sure if this is the ideal solution.







c++ qt templates stdstring qstring






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 31 '18 at 23:20









Flimzy

38.7k106597




38.7k106597










asked Dec 31 '18 at 23:19









Ben JonesBen Jones

608517




608517








  • 5





    Traits/Policy or simple overload seems fine to handle the difference part.

    – Jarod42
    Dec 31 '18 at 23:22








  • 1





    QString has begin() and end() members, so any range algorithm should work equally.

    – zett42
    Dec 31 '18 at 23:48











  • user zett42 has given an excellent and valid solution, however my answer provides an alternative approach that uses QString's toStdString() member function. Thought I'd just provide you with another working solution as it would increase your available toolset.

    – Francis Cugler
    Jan 2 at 1:14














  • 5





    Traits/Policy or simple overload seems fine to handle the difference part.

    – Jarod42
    Dec 31 '18 at 23:22








  • 1





    QString has begin() and end() members, so any range algorithm should work equally.

    – zett42
    Dec 31 '18 at 23:48











  • user zett42 has given an excellent and valid solution, however my answer provides an alternative approach that uses QString's toStdString() member function. Thought I'd just provide you with another working solution as it would increase your available toolset.

    – Francis Cugler
    Jan 2 at 1:14








5




5





Traits/Policy or simple overload seems fine to handle the difference part.

– Jarod42
Dec 31 '18 at 23:22







Traits/Policy or simple overload seems fine to handle the difference part.

– Jarod42
Dec 31 '18 at 23:22






1




1





QString has begin() and end() members, so any range algorithm should work equally.

– zett42
Dec 31 '18 at 23:48





QString has begin() and end() members, so any range algorithm should work equally.

– zett42
Dec 31 '18 at 23:48













user zett42 has given an excellent and valid solution, however my answer provides an alternative approach that uses QString's toStdString() member function. Thought I'd just provide you with another working solution as it would increase your available toolset.

– Francis Cugler
Jan 2 at 1:14





user zett42 has given an excellent and valid solution, however my answer provides an alternative approach that uses QString's toStdString() member function. Thought I'd just provide you with another working solution as it would increase your available toolset.

– Francis Cugler
Jan 2 at 1:14












2 Answers
2






active

oldest

votes


















2














Both std::string and QString have data() and size() members, so you could construct a std::basic_string_view for unified string operations:



#include <iostream>
#include <string_view>

template <typename StringType>
void do_something( StringType const& s, typename StringType::size_type start, typename StringType::size_type length )
{
std::basic_string_view sv( s.data(), s.size() );

auto sub_s = sv.substr( start, length );

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


Live Demo






share|improve this answer
























  • QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

    – Jarod42
    Jan 2 at 19:09



















1














As of the time of writing this completed answer, user zett42 has given a valid solution to your problem. It took me some time to properly install Qt and to integrate it into Visual Studio 2017, since now that I have it working I am now finally able to properly build and compile my code to make sure that it works without any issues or bugs.



I think the simplest thing to do would be to use QString's toStdString() function. You can write all of your functionality with the default std::string version, and then just specialize the QString overloaded version that just calls the std::string version by converting the contents of the QString to a std::string. I will use a simple printString() function to demonstrate this in the simplest manner; you can take this approach and expand it from here.



#include <string>
#include <iostream>
#include <QString>

// defaulted std::string version (full implementation of function)
template <typename StringType>
void printString(const StringType& s) {
std::cout << s << 'n';
}

// specialized overloaded QString version (it calls the std::string version)
template<>
void printString<QString>(const QString& s ) {
printString(s.toStdString());
}

int main() {
const std::string str( "I am an original std::string" );
const QString qStr( "I am a QString converted to a std::string" );

printString(str);
printString(qStr);

return 0;
}


-Output-



I am an original std::string
I am a QString converted to a std::string


I think this is the easiest way to achieve what you are asking for. This also has the advantage that if you have to make a modification to your implementation you only have to change the std::string version.






share|improve this answer


























  • You might use overload instead of specialization.

    – Jarod42
    Jan 2 at 19:03











  • You create (unnecessary) copy

    – Jarod42
    Jan 2 at 19:05











  • That can easily be fixed with move semantics: I can update the answer to reflect it.

    – Francis Cugler
    Jan 2 at 23:47











  • For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

    – Jarod42
    Jan 3 at 8:49











  • I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

    – Jarod42
    Jan 3 at 8:54











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
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53992090%2fhow-do-write-template-function-that-can-get-a-substring-of-a-qstring-or-a-stds%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














Both std::string and QString have data() and size() members, so you could construct a std::basic_string_view for unified string operations:



#include <iostream>
#include <string_view>

template <typename StringType>
void do_something( StringType const& s, typename StringType::size_type start, typename StringType::size_type length )
{
std::basic_string_view sv( s.data(), s.size() );

auto sub_s = sv.substr( start, length );

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


Live Demo






share|improve this answer
























  • QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

    – Jarod42
    Jan 2 at 19:09
















2














Both std::string and QString have data() and size() members, so you could construct a std::basic_string_view for unified string operations:



#include <iostream>
#include <string_view>

template <typename StringType>
void do_something( StringType const& s, typename StringType::size_type start, typename StringType::size_type length )
{
std::basic_string_view sv( s.data(), s.size() );

auto sub_s = sv.substr( start, length );

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


Live Demo






share|improve this answer
























  • QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

    – Jarod42
    Jan 2 at 19:09














2












2








2







Both std::string and QString have data() and size() members, so you could construct a std::basic_string_view for unified string operations:



#include <iostream>
#include <string_view>

template <typename StringType>
void do_something( StringType const& s, typename StringType::size_type start, typename StringType::size_type length )
{
std::basic_string_view sv( s.data(), s.size() );

auto sub_s = sv.substr( start, length );

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


Live Demo






share|improve this answer













Both std::string and QString have data() and size() members, so you could construct a std::basic_string_view for unified string operations:



#include <iostream>
#include <string_view>

template <typename StringType>
void do_something( StringType const& s, typename StringType::size_type start, typename StringType::size_type length )
{
std::basic_string_view sv( s.data(), s.size() );

auto sub_s = sv.substr( start, length );

// Do something with the substring, for instance:
std::cout << "Length of substring is " << sub_s.length() << std::endl;
}


Live Demo







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 1 at 2:30









zett42zett42

7,3633740




7,3633740













  • QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

    – Jarod42
    Jan 2 at 19:09



















  • QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

    – Jarod42
    Jan 2 at 19:09

















QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

– Jarod42
Jan 2 at 19:09





QString::data() /*const*/ returns /*const*/QChar*. Which is incompatible with std::basic_string_view

– Jarod42
Jan 2 at 19:09













1














As of the time of writing this completed answer, user zett42 has given a valid solution to your problem. It took me some time to properly install Qt and to integrate it into Visual Studio 2017, since now that I have it working I am now finally able to properly build and compile my code to make sure that it works without any issues or bugs.



I think the simplest thing to do would be to use QString's toStdString() function. You can write all of your functionality with the default std::string version, and then just specialize the QString overloaded version that just calls the std::string version by converting the contents of the QString to a std::string. I will use a simple printString() function to demonstrate this in the simplest manner; you can take this approach and expand it from here.



#include <string>
#include <iostream>
#include <QString>

// defaulted std::string version (full implementation of function)
template <typename StringType>
void printString(const StringType& s) {
std::cout << s << 'n';
}

// specialized overloaded QString version (it calls the std::string version)
template<>
void printString<QString>(const QString& s ) {
printString(s.toStdString());
}

int main() {
const std::string str( "I am an original std::string" );
const QString qStr( "I am a QString converted to a std::string" );

printString(str);
printString(qStr);

return 0;
}


-Output-



I am an original std::string
I am a QString converted to a std::string


I think this is the easiest way to achieve what you are asking for. This also has the advantage that if you have to make a modification to your implementation you only have to change the std::string version.






share|improve this answer


























  • You might use overload instead of specialization.

    – Jarod42
    Jan 2 at 19:03











  • You create (unnecessary) copy

    – Jarod42
    Jan 2 at 19:05











  • That can easily be fixed with move semantics: I can update the answer to reflect it.

    – Francis Cugler
    Jan 2 at 23:47











  • For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

    – Jarod42
    Jan 3 at 8:49











  • I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

    – Jarod42
    Jan 3 at 8:54
















1














As of the time of writing this completed answer, user zett42 has given a valid solution to your problem. It took me some time to properly install Qt and to integrate it into Visual Studio 2017, since now that I have it working I am now finally able to properly build and compile my code to make sure that it works without any issues or bugs.



I think the simplest thing to do would be to use QString's toStdString() function. You can write all of your functionality with the default std::string version, and then just specialize the QString overloaded version that just calls the std::string version by converting the contents of the QString to a std::string. I will use a simple printString() function to demonstrate this in the simplest manner; you can take this approach and expand it from here.



#include <string>
#include <iostream>
#include <QString>

// defaulted std::string version (full implementation of function)
template <typename StringType>
void printString(const StringType& s) {
std::cout << s << 'n';
}

// specialized overloaded QString version (it calls the std::string version)
template<>
void printString<QString>(const QString& s ) {
printString(s.toStdString());
}

int main() {
const std::string str( "I am an original std::string" );
const QString qStr( "I am a QString converted to a std::string" );

printString(str);
printString(qStr);

return 0;
}


-Output-



I am an original std::string
I am a QString converted to a std::string


I think this is the easiest way to achieve what you are asking for. This also has the advantage that if you have to make a modification to your implementation you only have to change the std::string version.






share|improve this answer


























  • You might use overload instead of specialization.

    – Jarod42
    Jan 2 at 19:03











  • You create (unnecessary) copy

    – Jarod42
    Jan 2 at 19:05











  • That can easily be fixed with move semantics: I can update the answer to reflect it.

    – Francis Cugler
    Jan 2 at 23:47











  • For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

    – Jarod42
    Jan 3 at 8:49











  • I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

    – Jarod42
    Jan 3 at 8:54














1












1








1







As of the time of writing this completed answer, user zett42 has given a valid solution to your problem. It took me some time to properly install Qt and to integrate it into Visual Studio 2017, since now that I have it working I am now finally able to properly build and compile my code to make sure that it works without any issues or bugs.



I think the simplest thing to do would be to use QString's toStdString() function. You can write all of your functionality with the default std::string version, and then just specialize the QString overloaded version that just calls the std::string version by converting the contents of the QString to a std::string. I will use a simple printString() function to demonstrate this in the simplest manner; you can take this approach and expand it from here.



#include <string>
#include <iostream>
#include <QString>

// defaulted std::string version (full implementation of function)
template <typename StringType>
void printString(const StringType& s) {
std::cout << s << 'n';
}

// specialized overloaded QString version (it calls the std::string version)
template<>
void printString<QString>(const QString& s ) {
printString(s.toStdString());
}

int main() {
const std::string str( "I am an original std::string" );
const QString qStr( "I am a QString converted to a std::string" );

printString(str);
printString(qStr);

return 0;
}


-Output-



I am an original std::string
I am a QString converted to a std::string


I think this is the easiest way to achieve what you are asking for. This also has the advantage that if you have to make a modification to your implementation you only have to change the std::string version.






share|improve this answer















As of the time of writing this completed answer, user zett42 has given a valid solution to your problem. It took me some time to properly install Qt and to integrate it into Visual Studio 2017, since now that I have it working I am now finally able to properly build and compile my code to make sure that it works without any issues or bugs.



I think the simplest thing to do would be to use QString's toStdString() function. You can write all of your functionality with the default std::string version, and then just specialize the QString overloaded version that just calls the std::string version by converting the contents of the QString to a std::string. I will use a simple printString() function to demonstrate this in the simplest manner; you can take this approach and expand it from here.



#include <string>
#include <iostream>
#include <QString>

// defaulted std::string version (full implementation of function)
template <typename StringType>
void printString(const StringType& s) {
std::cout << s << 'n';
}

// specialized overloaded QString version (it calls the std::string version)
template<>
void printString<QString>(const QString& s ) {
printString(s.toStdString());
}

int main() {
const std::string str( "I am an original std::string" );
const QString qStr( "I am a QString converted to a std::string" );

printString(str);
printString(qStr);

return 0;
}


-Output-



I am an original std::string
I am a QString converted to a std::string


I think this is the easiest way to achieve what you are asking for. This also has the advantage that if you have to make a modification to your implementation you only have to change the std::string version.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 3 at 8:46









Jarod42

117k12103185




117k12103185










answered Jan 2 at 1:01









Francis CuglerFrancis Cugler

4,67411227




4,67411227













  • You might use overload instead of specialization.

    – Jarod42
    Jan 2 at 19:03











  • You create (unnecessary) copy

    – Jarod42
    Jan 2 at 19:05











  • That can easily be fixed with move semantics: I can update the answer to reflect it.

    – Francis Cugler
    Jan 2 at 23:47











  • For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

    – Jarod42
    Jan 3 at 8:49











  • I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

    – Jarod42
    Jan 3 at 8:54



















  • You might use overload instead of specialization.

    – Jarod42
    Jan 2 at 19:03











  • You create (unnecessary) copy

    – Jarod42
    Jan 2 at 19:05











  • That can easily be fixed with move semantics: I can update the answer to reflect it.

    – Francis Cugler
    Jan 2 at 23:47











  • For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

    – Jarod42
    Jan 3 at 8:49











  • I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

    – Jarod42
    Jan 3 at 8:54

















You might use overload instead of specialization.

– Jarod42
Jan 2 at 19:03





You might use overload instead of specialization.

– Jarod42
Jan 2 at 19:03













You create (unnecessary) copy

– Jarod42
Jan 2 at 19:05





You create (unnecessary) copy

– Jarod42
Jan 2 at 19:05













That can easily be fixed with move semantics: I can update the answer to reflect it.

– Francis Cugler
Jan 2 at 23:47





That can easily be fixed with move semantics: I can update the answer to reflect it.

– Francis Cugler
Jan 2 at 23:47













For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

– Jarod42
Jan 3 at 8:49





For your changes, better to use const reference for printString, and remove all std::move. Edited to reflect my last remarks.

– Jarod42
Jan 3 at 8:49













I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

– Jarod42
Jan 3 at 8:54





I primary meant the "conversion" from QString to string does allocation which is not always wanted/accepted. Might be fine in some cases but if strings are huge, it might be really problematic.

– Jarod42
Jan 3 at 8:54


















draft saved

draft discarded




















































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.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53992090%2fhow-do-write-template-function-that-can-get-a-substring-of-a-qstring-or-a-stds%23new-answer', 'question_page');
}
);

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







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas