从C++中的模板函数返回字符串和整数
问题描述:
我想写一个通用函数,使用模板,能够返回布尔,整数或char *或字符串。从C++中的模板函数返回字符串和整数
template<typename entryType>
entryType getEntry(xml_node node, const char* entryKey)
{
...
if (is_same<entryType, bool>::value) {
return boolvalue; //returning a boolean
}
else if(is_same<entryType, int>::value) {
return a; //this is an integer
}
else if (is_same<entryType, char*>::value) {
return result; //this is a char*
}
}
,我希望能够调用它像:
bool bPublisher = getEntry<bool>(node, "Publisher");
int QoS = getEntry<int>(node, "QualityOfService");
char* sBrokerUrl = getEntry<char*>(node, "BrokerUrl");
作为字符*替代,一个字符串也将是罚款:
string sBrokerUrl = getEntry<string>(node, "BrokerUrl");
我得到错误,如:“不能从'bool'转换为'char *'我理解这个问题,编译器无法检测到代码执行分支取决于我给的类型,我只是找不到解决方案任何人都可以帮助我吗? NKS。
答
如果C++ 17不提供给你,模板特可能会做你想要什么:
template<typename entryType>
entryType getEntry(xml_node node, const char* entryKey) {}
template<>
bool getEntry<bool>(xml_node node, const char* entryKey) {
return true;
}
template<>
int getEntry<int>(xml_node node, const char* entryKey) {
return 1;
}
你可以把任何共享代码在从每个专业调用的帮助函数中:
void shared_code(xml_node node, const char* entryKey) {
// ...
}
template<>
bool getEntry<bool>(xml_node node, const char* entryKey) {
shared_code(node, entryKey);
return true;
}
template<>
int getEntry<int>(xml_node node, const char* entryKey) {
shared_code(node, entryKey);
return 1;
}
答
既然C++ 17可以使用constexpr if;其条件部分将在编译时进行评估,如果结果是true
则声明false部分(否则声明真实部分)将被丢弃。 (因此不会导致错误。)例如
if constexpr (is_same<entryType, bool>::value) {
return boolvalue; //returning a boolean
}
else if constexpr (is_same<entryType, int>::value) {
return a; //this is an integer
}
else if constexpr (is_same<entryType, char*>::value) {
return result; //this is a char*
}
答
对于旧版本的C++的,您可以通过转发来的重载函数返回通过引用传递参数导致一个解决这个问题:
template<typename entryType>
entryType getEntry(xml_node node, const char* entryKey)
{
entryType result = entryType();
this->getEntry(node, entryKey, result);
return result;
}
void getEntry(xml_node node, const char* entryKey, bool& result);
void getEntry(xml_node node, const char* entryKey, int& result);
void getEntry(xml_node node, const char* entryKey, char const *& result);
或者你可以使用std::enable_if
(因为C++ 11):
template<typename entryType>
typename std::enable_if<std::is_same<entryType, bool>::value, entryType>::type
getEntry(xml_node node, const char* entryKey) {
...
}
但首先IMO的解决方案更具可读性。如果你不想公开它们,你可以使重载函数保密。
答
像@ tobi303在评论中说,你应该专注于模板。 没有必要花哨的SFINAE或其他技巧。
#include <iostream>
#include <type_traits>
using namespace std;
template<typename entryType>
entryType getEntry(const char* entryKey);
template <>
int getEntry<int>(const char* entryKey)
{
return 1;
}
template <>
bool getEntry<bool>(const char* entryKey)
{
return false;
}
template <>
string getEntry<string>(const char* entryKey)
{
return "asd";
}
int main() {
bool bPublisher = getEntry<bool>("Publisher");
int QoS = getEntry<int>("QualityOfService");
string sBrokerUrl = getEntry<string>("BrokerUrl");
cout << bPublisher << '\n' << QoS << '\n'<< sBrokerUrl << '\n';
}
答
我想我会倾向于利用的std::tuple
本已出色的功能性。
将标记值和标记值组合在一起,并且可以用最少的努力为这种事物生成富有表现力的,类型安全的代码。
#include <iostream>
#include <tuple>
template<class Tag, class Type>
struct xmlvalue : Type
{
using Type::Type;
};
template<class Tag> struct xmlvalue<Tag, bool>
{
xmlvalue(bool v) : value_(v) {}
operator bool&() { return value_; }
operator bool const&() const { return value_; }
private:
bool value_;
};
template<class Tag> struct xmlvalue<Tag, int>
{
xmlvalue(int v) : value_(v) {}
operator int&() { return value_; }
operator int const&() const { return value_; }
private:
int value_;
};
struct is_publisher_tag {};
struct qos_tag {};
struct broker_url_tag {};
using is_publisher = xmlvalue<is_publisher_tag, bool>;
using qos = xmlvalue<qos_tag, int>;
using broker_url = xmlvalue<broker_url_tag, std::string>;
struct quote : std::tuple<is_publisher , qos, broker_url >
{
using std::tuple<is_publisher , qos, broker_url >::tuple;
};
int main() {
auto q1 = quote(true, 100, "http:://foo.com");
auto q2 = quote(false, 50, "http:://bar.com");
std::cout << std::get<broker_url>(q1) << ", " << std::get<qos>(q1) << ", " << std::get<is_publisher>(q1) << std::endl;
std::cout << std::get<broker_url>(q2) << ", " << std::get<qos>(q2) << ", " << std::get<is_publisher>(q2) << std::endl;
return 0;
}
预期输出:
http:://foo.com, 100, 1
http:://bar.com, 50, 0
那么,你不能用普通的'if'语句来做到这一点。 –
如果语句 –
需要专门化模板,则不能依赖运行时的返回类型。毕竟,一旦编译完成,tempalte就成为一个返回类型明确的普通函数 – user463035818