如何允许编译器推断出正确的返回类型以进行模板get函数

How to allow compiler to deduce correct return type for templated get function?

本文关键字:函数 get 返回类型 编译器 何允许 推断出      更新时间:2023-10-16

我有很多结构,所有结构都有一些元素:

struct myExample
{
    std::string elem0;
    int elem1;
};

如果我可以让以下内容工作,我可以避免大量编码。编写一个模板GET方法,该方法将索引作为模板参数并从上面的结构返回elem。

template<int idx, typename K, typename T> T get(const K&) 
{ 
    throw std::runtime_error("should not happen");
}
template<> std::string get<0, myExample, std::string>(const myExample& k)
{
    return k.elem0;
}
template<> int get<1, myExample, int>(const myExample& k)
{
    return k.elem1;
}

这是该示例的主要功能:

int main() 
{
    myExample test;
    test.elem0 = "hello world";
    test.elem1 = 42;
    // does not work:
    //std::string get0 = ::get<0>(test);
    //int get1 = ::get<1>(test);
    // does not work either:
    //std::string get0 = ::get<0, myExample>(test);
    //int get1 = ::get<1, myExample>(test);
    // works:
    std::string get0 = ::get<0, myExample, std::string>(test);
    int get1 = ::get<1, myExample, int>(test);
    std::cout<<get0<<":"<<get1<<std::endl;
    return 0;
}

我想使用 ::get<0>(test),但是由于某种原因,编译器抱怨 call call call to to'get(myexample&amp;('即使至少要引发错误的模板函数可用,对吗?

原则上应该可以告诉编译器正确的返回类型,因为ELEM0和ELEM1的类型是在编译时定义的。

如何扩展此类似元组的结构以返回正确的类型,而无需手动写出它?

到目前为止,这与较旧的C 版本一起使用,这就是我不应该给我们自动之类的原因。没有C 11?

请在Ideone上查看示例。

您的输入非常感谢!

编译器必须在考虑专业知识之前推论所有模板参数,并且它无法以这种方式推断T

只需完全删除typename T参数,而不需要。


您可能还想考虑一个更容易的选择:

template <int Index, typename T> auto get(const T &object)
{
    return std::get<Index>(std::tie(object.elem0, object.elem1, object.elem2));
}

不要使用模板功能专业化,几乎总是一个坏主意。

而是使用过载和转发。

template<int idx>
using index_t = std::integral_constant<int, idx>;
// compile time error if it doesn't match
template<int i, class K>
void special_get(index_t<i>, const K&) = delete;
template<int idx, typename K> 
decltype(special_get( index_t<idx>{}, std::declval<K const&>() ) )
get(const K& k) { 
  return special_get( index_t<idx>{}, k );
}

没有专业。

inline std::string special_get(index_t<0>, const myExample& k) {
  return k.elem0;
}
inline int special_get(index_t<1>, const myExample& k) {
  return k.elem1;
}

这些是special_get的过载。选择哪一个是通过超载分辨率选择的,而不是模板专业化。

模板功能的专业化不应是解决任何问题的第一个,第二或第三选择。

我认为您有一个小错字,可能会使编译器试图解决模板感到困惑。在这两行中:

template<> int get<2, myExample, int>(const myExample& k) { return k.elem1_; }
template<> boost::gregorian::date get<2, myExample, boost::gregorian::date>(const myExample& k) { return k.elem2_; }

您的两个模板都有相同的索引,2。我认为您的意思是INT专业化。

所以我想在某些情况下,对于索引2,编译器无法在INT和日期之间做出决定。