"AnySTLContainer <int>"c ++的模板

S.H*_*S.H 10 c++ templates stl template-argument-deduction

我正在寻找一种方法来提供一个带模板(STL)容器的函数,但需要它的元素是某种类型(例如int).

这些函数调用应该是VALID:

std::vector<int> Argument;
void foo( Argument );

std::list<int> Argument
void foo( Argument );

std::deque<int> Argument
void foo( Argument );

...etc
Run Code Online (Sandbox Code Playgroud)

这些函数调用应该是INVALID:

std::vector<float> Argument;
void foo( Argument );

std::list<double> Argument
void foo( Argument );

std::deque<char> Argument
void foo( Argument );

...etc
Run Code Online (Sandbox Code Playgroud)

有没有办法模板"foo",以便int接受容器,但不接受具有不同元素类型的容器?

最好,本

qua*_*dev 13

使用标准库语义:

  • 通过一对迭代来的foo,而不是一个容器:它使你的功能很多更通用
  • 使用std::iterator_traits<Iterator>::value_type得到的值类型
  • static_assertIterator的值类型是int(或者你想要的任何类型)

示例:

#include <list>
#include <vector>

template<typename Iterator>
void foo(Iterator begin, Iterator end)
{
    static_assert(std::is_same<int, typename std::iterator_traits<Iterator>::value_type>::value, 
                                "Invalid value type : must be int");
}

int main() {
    std::list<int> l1;
    std::vector<int> v1;

    foo(std::begin(l1), std::end(l1)); // OK
    foo(std::begin(v1), std::end(v1)); // OK

    std::vector<float> v2;
    foo(std::begin(v2), std::end(v2)); // Doesn't compile
}
Run Code Online (Sandbox Code Playgroud)

现场演示

注意:

  • 如果 foo需要访问容器的特定成员函数(如Deduplicator所述,出于性能原因可能会发生这种情况),那么您可能需要坚持使用Container参数:

示例:(注意获取的差异value_type,如MooingDuck所指出的,这是使其适用于数组所必需的):

template <typename Container>
void foo(const Container& c)
{

    static_assert(std::is_same<int, std::iterator_type<decltype(std::begin(c))>::value_type>::value, "Invalid value type : must be int");

   // Use c member function(s)
}
Run Code Online (Sandbox Code Playgroud)

  • @black除了概念没有进入C++ 14 (6认同)

Jar*_*d42 9

STL容器有typedef value_type,所以你可以使用它.

然后你可以禁止static_assert:

template <typename Container>
void foo(const Container& )
{
    static_assert(std::is_same<int, typename Container::value_type>::value, "expect int type");
}
Run Code Online (Sandbox Code Playgroud)

或通过SFINAE

template <typename Container>
typename std::enable_if<std::is_same<int, typename Container::value_type>::value>::type
foo(const Container& )
{
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*son 4

您可以简单地使用 Sfinae,如下所示:

#include <type_traits>
#include <utility>

template <typename Container>
typename std::enable_if< std::is_same< typename Container::value_type, int >::value,
void >::type foo(Container& c) {
  /* code here */
};
Run Code Online (Sandbox Code Playgroud)

如果容器没有与“int”相同的值类型,则将从“foo”的重载集中删除。您还可以使用其他特征,例如is_convertible更容易接受相关类型。使用不具有 int 值的容器调用 foo 会被编译器报告为没有合适的重载候选者。

如果您没有 C++11 支持,我上面使用的东西可以在 Boost 中作为 C++98/03 的替代品。