模板模板参数,计为一个参数

时间:2013-10-03 16:12:00

标签: c++ templates function-templates template-templates

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

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

此问题与function overload matching template template

相关联
#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.
}

2 个答案:

答案 0 :(得分: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);
}

或者,请考虑Jarod42suggestion

答案 1 :(得分: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);
}