2

在下面的代码中,类模板使用一个参数,但如果模板参数是模板,则函数模板使用两个。这在使用类型推导时没问题,但在使用显式模板实例化时很奇怪。

是否可以将模板模板参数写为一个参数?

这个问题链接到函数重载匹配模板模板

#include <iostream>

template <typename T>
struct C
{
    C (T i)
    {
        std::cout << "simple" << std::endl;
    }
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> >          // (1)
{
    C (FF<TT> i)
    {
        std::cout << "template" << std::endl;
    }
};
template <typename T>
void F (T i)
{
    std::cout << "simple" << std::endl;
}

// two template arguments FF and TT.
// Anyway to write this so that the argument count is one?
template <template<typename TT> class FF, typename TT>
void F (FF<TT> i)
{
    std::cout << "template" << std::endl;
}

template <typename T>
struct R
{
    T x;
};
int main()
{
        R<int>     r;
        C<R<int> >{r};      // prints 'template', as expected
        F<R<int> >(r);      // prints 'simple',  probably not what you think
        F<R,int  >(r);      // prints 'template' as expected but 
}

编辑:

我得出的结论是这个问题不是一个好问题,因为如果有一个参数语法,重载决议仍然会选择错误的函数。这让我感到惊讶,但这里是证明它的代码(与以前相同的代码,除了一个模板函数重载发生了变化):

EDIt2:在跳过显式模板规范的主要内容中添加了进一步的打印。

EDIT3:下面的代码是废话。正如@DyP 正确指出的那样,我犯了一个错误。我void F(R<R<T>>)在明确的情况下打电话而不是void F(R<T>).

#include <iostream>

template <typename T>
struct R
{
    T x;
};
template <typename T>
struct C
{
    C (T i)
    {
        std::cout << "simple" << std::endl;
    }
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> >          // (1)
{
    C (FF<TT> i)
    {
        std::cout << "template" << std::endl;
    }
};
template <typename T>
void F (R<T> i)
{
    std::cout << "template" << i.x << std::endl;
}
template <typename T>
void F (T i)
{
    std::cout << "simple" << std::endl;
}
int main()
{
        R<int>     r;
        C<R<int> >{r};      // prints 'template', as expected
        F<R<int> >(r);      // prints 'simple',  probably not the expected overload
        F         (r);      // prints 'template', now overload resolution works. Strange.
}
4

2 回答 2

1

使用 SFINAE:

#include <type_traits>

template<class T>
struct is_template_with_one_param
: std::false_type
{};

template<template<class> class TT, class T>
struct is_template_with_one_param< TT<T> >
: std::true_type
{};


#include <iostream>

template <typename T>
typename std::enable_if< not is_template_with_one_param<T>{}, void >::type
F (T i)
{
    std::cout << "simple" << std::endl;
}

template <typename T>
typename std::enable_if< is_template_with_one_param<T>{}, void >::type
F (T i)
{
    std::cout << "template" << std::endl;
}

用法示例:

template <typename T>
struct R
{
    T x;
};
int main()
{
        F(R<int>{});
        F(42);
}

或者,考虑Jarod42建议

于 2013-10-03T16:29:43.540 回答
0

另一种可能的解决方案:

#include <iostream>

template <typename T>
struct C
{
    C (T i)
    {
        std::cout << "simple" << std::endl;
    }
};
template <template<typename TT> class FF, typename TT>
struct C <FF<TT> >          // (1)
{
    C (FF<TT> i)
    {
        std::cout << "template" << std::endl;
    }
};

template <typename T>
void F (T i)
{
    C<T> x(i);
}

template <typename T>
struct R
{
    T x;
};
int main()
{
        R<int>     r;
        F(r);
        F(4);
}
于 2013-10-03T16:40:37.757 回答