繁体   English   中英

C++ 模棱两可的模板重载

[英]C++ ambiguous template overloads

我正在尝试使用模板特化根据模板变量的值返回不同的类型。

我已经不再尝试在运行时分支,而不是在编译时使用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()

任何帮助将不胜感激。

您的问题是template<typename T> T getVal()当 SFINAEd 成功时使调用模棱两可。

一种解决方案是限制具有补码条件的那个...

但是标签调度是解决问题的一种简单替代方法:

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()很容易地做到这一点,尽管您可能过于简化了问题

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM