【问题标题】:Specialize template for any vector<any_arithmetic_data_type>为任何向量专门化模板<any_arithmetic_data_type>
【发布时间】:2011-09-29 09:30:09
【问题描述】:

我有一个模板方法,它有两个专用版本,用于类型 boolvector&lt;string&gt;

基础版本:

template <class T> 
const T InternGetValue(const std::string& pfad) const
{
  ...   
}

特殊版本:

template <>
const bool InternGetValue(const std::string& pfad) const
{
  ...
}  

template <>
const std::vector<std::string> InternGetValue< std::vector<std::string>>(const std::string& pfad) const
{
...
}

现在我想实现 one 专业化,它将接受所有类型的 vector&lt;aritmethic_data_type&gt;,例如 vector&lt;double&gt; vector&lt;int&gt;vector&lt;float&gt;

我可以通过为上述类型编写重载来实现这一点,但我有兴趣通过另一个专业来实现我的目标。

这是我迄今为止尝试过的(导致错误“非法使用显式模板参数”):

template <class T>
const std::vector<T> InternGetValue< std::vector<T>>(const std::string& pfad, typename boost::enable_if<boost::is_arithmetic<T>>::type* dummy = 0) const
{
}

【问题讨论】:

  • 完全专业化的功能模板很少有用。重载方法有什么问题?
  • @TomalakGeret'kal:重载方法当然没有错。我只是好奇如何通过专业化解决它。拓宽我的视野...... :-)
  • 很公平。只要你掌握了所有的事实。 :)

标签: c++ templates boost


【解决方案1】:

我认为std::enable_ifstd::is_integral一起可以解决这个问题:

template<typename T>
std::vector<typename std::enable_if<std::is_integral<T>::value, T>::type> 
f(const std::string& d);

如果std:: 没有它们,请尽可能使用boost::。它有它们。

【讨论】:

  • 您的示例中似乎有一个小错字:enable_if&lt;std::is_integral&lt;T&gt;&gt;, T&gt; 应该是正确的。但是更正后还有一个编译错误:ambiguous call to overload function。我猜你提供的模板方法与我对vector&lt;string&gt; 的专长有冲突?
  • 我也不明白你在vector 返回值声明中对enable_if 的使用。什么是`vector?你能解释一下吗?
  • @nabulke:抱歉,必须是typename std::enable_if&lt;std::is_integral&lt;T&gt;::value, T&gt;::type。已更正。
  • 抱歉,您的示例中 的数量不匹配。不会编译。应该是&lt;typename std::enable_if&lt;std::is_integral&lt;T&gt;::value, T&gt; &gt;::type
  • 如果你想使用 Boost,请注意 std::enable_if 的替换不是 boost::enable_if 而是 boost::enable_if_c。或者你可以使用boost::enable_if&lt;boost::is_integral&lt;T&gt;, T&gt;(没有::value)。我希望这两个版本都包含在标准中...
【解决方案2】:

好吧,超级复杂,但我把一切都搞定了。我不能只在第一个(默认)函数重载内的 value_type 类型上检查 is_integral,因为这会导致 SFINAE 删除非向量的重载。

与 Nawaz 的解决方案不同,这不需要添加虚拟参数,但它确实需要默认函数模板上的 enable_if 条件。

这适用于 VS2010。

#include <vector>
#include <string>
#include <type_traits>

using namespace std;

template <typename T> struct is_vector { static const bool value = false; };
template <typename T> struct is_vector< std::vector<T> > { static const bool value = true; };

// metafunction to extract what type a vector is specialised on
// vector_type<vector<T>>::type == T
template <class T>
struct vector_type
{
private:
    template <class T>
    struct ident
    {
        typedef T type;
    };

    template <class C> 
    static ident<C> test(vector<C>);

    static ident<void> test(...);

    typedef decltype(test(T())) vec_type;
public:
    typedef typename vec_type::type type;
};

// default version
template <class T>
const typename enable_if<!is_vector<T>::value || !is_integral<typename vector_type<T>::type>::value, T>::type
InternGetValue(const std::string& pfad)
{
    return T();
}

// bool specialisation
template <>
const bool
InternGetValue<bool>(const std::string& pfad)
{
    return true;
}

// vector<string> specialisation
template <>
const vector<string>
InternGetValue<vector<string>>(const std::string& pfad)
{
    return vector<string>();
}

// vector<T> specialisation (where T is integral)
template <class T>
const typename enable_if<is_vector<T>::value && is_integral<typename vector_type<T>::type>::value, T>::type
InternGetValue(const std::string& pfad)
{
    return T();
}

int main()
{
    string x;
    auto a = InternGetValue<int>(x);
    auto b = InternGetValue<bool>(x);
    auto c = InternGetValue<vector<string>>(x);
    auto d = InternGetValue<vector<pair<int, int>>>(x);
    auto e = InternGetValue<vector<int>>(x);
}

【讨论】:

  • 我可能遗漏了一些东西,但您确定需要 SFINAE 来测试某个东西是否是向量吗?沿着这些路线做一些事情还不够吗? template &lt;typename T&gt; struct is_vector { static const bool value = false; }; template &lt;typename T&gt; struct is_vector&lt; std::vector&lt;T&gt; &gt; { static const bool value = true; };
  • 要访问向量中包含的值的类型,可以使用::value_type:std::vector&lt;T&gt;::value_type == T
  • 对于 is_vector,你是绝对正确的!这要简单得多。但是,对于vector_type,我无法获得第一个(默认)函数来专门针对非向量。如果您将typename T::value_type 替换为typename vector_type&lt;T&gt;::type,SFINAE 将防止为非向量生成重载。
  • 用更简单的 is_vector 元函数更新了我的答案
  • 确实,当类型不是vector 时,访问value_type 可能会出现问题。也许最好的方法是定义一个元函数is_vector_of_integral,或者更好的是is_vector_of:template &lt;typename Type, template &lt;typename&gt; class Predicate&gt; struct is_vector_of { static const bool value = false; }; template &lt;typename ValueType, template &lt;typename&gt; class Predicate&gt; struct is_vector_of&lt; std::vector&lt;ValueType&gt;, Predicate &gt; : Predicate&lt;ValueType&gt; {};。可以这样使用:is_vector_of&lt;std::vector&lt;int&gt;, std::is_integral&gt;::value.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-01
  • 2015-06-15
相关资源
最近更新 更多