Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;模版重载不明确_C++_Templates_Template Specialization - Fatal编程技术网

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