我正在尝试使用模板专门化以根据模板变量的值返回不同的类型。
我已经从尝试在运行时分支而不是使用typeof()
,非专业模板以及使用std::enable_if_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>();
}
我希望这可以解决三个不同的功能,但是我不确定是否是这样:
T Test::getVal()
int Test::getVal()
float Test::getVal()
任何帮助将不胜感激。
答案 0 :(得分:0)
您的问题是,当SFINAEd成功通过template<typename T> 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;
};
答案 1 :(得分:0)
您可以通过专门设置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>();
}
如果您能够使用c ++ 17,则使用if constexpr
和单个getVal
会更简单
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();
}
}