C++ C++;模版重载不明确
我试图使用模板专门化来根据模板变量的值返回不同的类型 我已经不再尝试在运行时进行分支,而是在编译时使用C++ C++;模版重载不明确,c++,templates,template-specialization,C++,Templates,Template Specialization,我试图使用模板专门化来根据模板变量的值返回不同的类型 我已经不再尝试在运行时进行分支,而是在编译时使用typeof()、非专用模板和std::enable\if\u t。我认为这可能是因为对模板函数的解析方式缺乏了解 class Test { public: template <typename T> T request() { T ret = getVal<T>(); return ret; } priv
typeof()
、非专用模板和std::enable\if\u t
。我认为这可能是因为对模板函数的解析方式缺乏了解
class Test
{
public:
template <typename T>
T request()
{
T ret = getVal<T>();
return ret;
}
private:
float foo = 2.f;
int bar = 1;
template <typename T>
typename std::enable_if<std::is_same<T, float>::value, bool>::type
getVal() { return foo; }
template <typename T>
typename std::enable_if<std::is_same<T, int>::value, bool>::type
getVal() { return bar; }
template<typename T>
T getVal()
{
std::cout << "T is type " << typeid(T).name() << std::endl;
throw std::bad_typeid();
}
};
int main()
{
Test t;
int i;
float f;
i = t.template request<int>();
f = t.template request<float>();
}
任何帮助都将不胜感激。您的问题是
template T getVal()
当指定的调用成功时,使调用不明确
一个解决方案是限制具有补足条件的一个
但标记分派是解决问题的一种简单的替代方法:
template <typename> struct Tag{};
class Test
{
public:
template <typename T>
T request() const
{
return getVal(Tag<T>{});
}
private:
float foo = 2.f;
int bar = 1;
float getVal(Tag<float>) const { return foo; }
int getVal(Tag<int>) const { return bar; }
template<typename T> void getVal(Tag<T>) = delete;
};
模板结构标记{};
课堂测试
{
公众:
模板
请求()常量
{
返回getVal(标记{});
}
私人:
浮点数foo=2.f;
int bar=1;
float getVal(Tag)const{return foo;}
int getVal(Tag)const{return bar;}
模板void getVal(Tag)=删除;
};
通过专门化getVal()
,您可以很容易地做到这一点,尽管您可能过于简化了这个问题
class Test {
public:
template <typename T>
T request() {
T ret = getVal<T>();
return ret;
}
private:
float foo = 2.f;
int bar = 1;
template<typename T>
T getVal() {
std::cout << "T is type " << typeid(T).name() << std::endl;
throw std::bad_typeid();
}
};
// add specializations
template<>
float Test::getVal<float>() { return foo; }
template <>
int Test::getVal<int>() { return bar; }
int main() {
Test t;
int i = t.request<int>(); // don't need template keyword here
float f = t.request<float>();
}
为什么不使用普通模板专门化?类似于以下的操作可能会起作用:
template T getVal(){/*default impl*/}。。。模板int getVal(){return bar;}。。。模板float getVal(){return foo;}
在这里运行的问题之一是getVal
将匹配getVal
的第二个和第三个声明,并且将是模糊的。你在这里的最终目标是什么?如果这个问题是出于好奇而产生的,那么这是一种非常不寻常的使用模板和更好的示例的方式,有助于更好地理解。我不认为这个问题完全回答了同一个问题,因为GC::Allocate
在该实例中成功地解决了问题,而Test::request()
未在此处解析。在这种情况下,向函数传递附加参数的解决方案没有帮助,因为目标是从另一个类的initilizer列表中的测试中获取一个值。虽然这超出了示例的范围,但要解决模糊问题,您需要将上一个版本更改为仅适用于非int
或float
的类型<代码>类型名称标准::启用\如果::值&&!std::is_same::value,bool>::例如,键入getVal,“虽然这超出了示例的范围”,但事实并非如此。你想通过这段代码实现什么是完全相关的,只有当你告诉我们你想实现什么时,我们才能告诉你如何实现它,仅仅修复编译器错误永远不会导致干净的编码。专用化应该在使用前始终可见(ODR)。使用C++17解决方案的结果是无缺陷的。如果将throw
替换为static\u assert(总是\u false,“!”)
,则编译时错误可能比运行时错误更好。
class Test {
public:
template <typename T>
T request() {
T ret = getVal<T>();
return ret;
}
private:
float foo = 2.f;
int bar = 1;
template<typename T>
T getVal() {
std::cout << "T is type " << typeid(T).name() << std::endl;
throw std::bad_typeid();
}
};
// add specializations
template<>
float Test::getVal<float>() { return foo; }
template <>
int Test::getVal<int>() { return bar; }
int main() {
Test t;
int i = t.request<int>(); // don't need template keyword here
float f = t.request<float>();
}
template<typename T>
auto getVal() {
if constexpr (std::is_same_v<int, T>) {
return foo;
} else if constexpr (std::is_same_v<float, T>) {
return bar;
} else {
std::cout << "T is type " << typeid(T).name() << std::endl;
throw std::bad_typeid();
}
}