在函数调用时避免模板规范

Avoiding template specification at function call

本文关键字:函数调用      更新时间:2023-10-16

我使用模板,我讨厌用模板参数调用函数。例子:

我有一个模板结构

template<typename T>
struct telement {
    typedef {
        T element;
        float some_value;
    } type;
};
telement<float>::type theElement;

和我有一个函数:

template<typename T>
float do_some_stuff( const typename telement<T>::type& x) {
    // ...
}
不幸的是,当我调用 时,g++会报错。
do_some_stuff( theElement );

and I must call:

do_some_stuff<float>( theElement );

每次调用函数都可以避免模板规范吗?我认为编译器应该自动找出类型…

这是不可演绎的上下文之一。编译器不能推导出模板参数T

问自己这个问题:当你写这篇文章的时候,

do_some_stuff( theElement );

你认为T应该推断什么类型的参数?

你可能认为是T=float ?嗯,这只是一种可能性。可以存在类模板的专门化,如:

//the compiler cannot assume that such specialization doesn't exist!
template<>
struct telement<someType>
{
    typedef {
        float element;
        float some_value;
    } type;
};

即使在这种情况下,嵌套类型telement<someType>::typetelement<float>::type相同。你看到模棱两可了吗?T和嵌套的type之间没有一一对应的关系。事实上可能存在多重关系。可以有许多T,它们的嵌套类型是相同的。

那么给定嵌套类型,编译器如何决定模板参数?它不能

已经有几个关于SO的主题解释了类似的情况,参见这些:

  • c++,模板参数不能推导
  • 专业iterator_traits

解决方案是,只需将函数模板编写为:
template<typename T>
float do_some_stuff( const T& x) {
    // ...
}

毕竟,在形参中写telement<T>::type有什么意义呢?

这是一种使用它的方法:

#include <iostream>

template<typename T>
struct telement {
    typedef struct {
        typedef T t_element_type;
        typedef float t_value_type;
        t_element_type element;
        t_value_type some_value;
    } type;
};

template<typename T>
float imp_do_some_stuff(const typename telement<T>::type& x) {
    return x.some_value;
}
template<typename T>
float do_some_stuff(const T& x) {
    return imp_do_some_stuff<typename T::t_element_type>(x);
}
int main() {
    telement<float>::type theElement;
    do_some_stuff(theElement);
    return 0;
}