4

我有以下演示代码:

template <int i, typename T, typename U>
T func(const U &t){return i * t;}

template <int i, typename T>
T func(const T &t){return 2 * i * t;}

int main()
{
        return func<1, int>(1);
}

这是我真实代码的简化版本,所以它似乎没用,但应该足以说明问题:

In function ‘int main()’:                                                  
11:23: error: call of overloaded ‘func(int)’ is ambiguous
11:23: note: candidates are:
2:3: note: T func(const U&) [with int i = 1, T = int, U = int]
5:3: note: T func(const T&) [with int i = 1, T = int]

所以很明显,自动类型推断(对于模板参数 U)干扰了我选择正确版本的模板函数(只有 2 个参数)的兴趣

我需要两个版本都有一个基本的和一个专门的模板,做的事情有点不同。

所以问题是:有没有可能告诉编译器此时不要自动推断类型(例如通过某种方式说:采用只有 2 个参数的模板)?

4

2 回答 2

4

您不能禁用类型推断,但可以使用 SFINAE 来禁止其中一种重载:

template <int N, typename T, typename U>
typename std::enable_if< !std::is_same<T,U>::value, T >::type
func( const U & t ) {
   return i*t;
}

U这基本上创建了一个模板化函数,如果推断的类型是 type ,则替换将失败T,此时 SFINAE 将从潜在候选集中删除该模板,并选择另一个模板。

如果您没有启用 C++11 的编译器,则enable_ifis_same模板很容易编写……只需在谷歌上搜索它们或发表评论。

于 2012-03-30T15:07:19.120 回答
1

您可以传递一个初始化列表,它可以有效地禁用推导(但会导致参数的列表初始化,但在这种情况下int具有相同的效果):

template <int i, typename T, typename U>
T func(const U &t){return i * t;}

template <int i, typename T>
T func(const T &t){return 2 * i * t;}

int main()
{
        return func<1, int>({1});
}

但在你的情况下,如果你打电话,func<N>(...)你似乎想打电话给第二个,如果你打电话,func<N, T>(...)你似乎也总是想打电话给第二个,而且只有func<N, T, U>(...)你想打电话给第一个,所以你总是可以禁用U通过使参数成为它的非推导上下文来推导

template <int i, typename T, typename U>
T func(typename std::common_type<const U &t>::type t){return i * t;}

template <int i, typename T>
T func(const T &t){return 2 * i * t;}

int main()
{
        return func<1, int>({1});
}
于 2012-03-31T19:02:02.363 回答