我在使用模板模板参数方面遇到了一些麻烦.这是一个非常简单的例子:
template <typename T>
struct Foo {
T t;
};
template <template <class X> class T>
struct Bar {
T<X> data;
X x;
};
int main()
{
Bar<Foo<int>> a;
}
Run Code Online (Sandbox Code Playgroud)
编译器(g ++(Ubuntu 4.8.2-19ubuntu1)4.8.2)报告以下错误:
main.cpp:8:5: error: ‘X’ was not declared in this scope
T<X> data;
^
main.cpp:8:6: error: template argument 1 is invalid
T<X> data;
^
Run Code Online (Sandbox Code Playgroud)
知道什么是错的吗?
如果我需要foo使用template-template参数定义模板函数,我通常会执行以下操作:
// Notice that the template parameter of class T is unnamed.
template <template <typename> class T> void f() { std::cout << "Yay!\n"; }
Run Code Online (Sandbox Code Playgroud)
请注意,template-template参数的template参数是未命名的,但我们可以为此参数指定一个名称:
// Now the template parameter of class T is named INNER.
template <template <typename INNER> class T> void f(const INNER &inner)
{ std::cout << inner << " Yay!\n"; }
Run Code Online (Sandbox Code Playgroud)
这似乎没有用,因为我无法INNER在函数中提供参数,上面的代码会产生以下错误:
错误:'INNER'未命名类型
令我惊讶typename INNER的typename是,在为了命名类型之后,所有关键字都没有命名类型.无论如何,这很容易修复:
// Now INNER is the name of the template parameter of class T and …Run Code Online (Sandbox Code Playgroud) 请考虑以下代码:
template<typename T>
struct A { };
// same as A, but with one extra defaulted parameter
template<typename T, typename F = int>
struct B { };
template<template<typename> typename T>
T<int> build() { return {}; }
int main()
{
build<A>(); // works in gcc and clang
build<B>(); // works in gcc, does not work in clang
}
Run Code Online (Sandbox Code Playgroud)
g ++(7.3.0)编译代码就好了,但是,clang ++(5.0.1)会发出以下命令:
example.cpp:14:5: error: no matching function for call to 'build'
build<B>(); // works in gcc, does not work in clang
^~~~~~~~ …Run Code Online (Sandbox Code Playgroud) 以下荒谬的示例无法编译,但是还有其他方法可以将变量模板作为模板模板参数传递吗?
template<typename T>
constexpr auto zero = T{0};
template<typename T, template<typename> auto VariableTemplate>
constexpr auto add_one()
{
return VariableTemplate<T> + T{1};
}
int main()
{
return add_one<int, zero>();
}
Run Code Online (Sandbox Code Playgroud)
我在Debian上使用gcc 4.4.请考虑以下代码.
#include <map>
#include <string>
using std::map;
using std::string;
// Args lets the user specify additional explicit template arguments
template <typename T,
template <typename T, typename... Args> class C,
typename... Args>
C<T, Args...> foo()
{
C<T, Args...> x;
return x;
}
int main(void)
{
map<string, int> a = foo<string, map, int>();
}
Run Code Online (Sandbox Code Playgroud)
所以,这里的想法是T匹配string,C匹配map和模板参数包Args匹配int.我可能有一些错误的语法,如果是这样,请更正.特别是,如果希望第一个模板参数class C匹配T而其余模板参数匹配模板参数包Args,template <typename T, typename... Args> class C …
以下是我的问题的SSCCE示例:
// My Library, which I want to take in the user's enum and a template class which they put per-enum specialized code
template <typename TEnum, template <TEnum> class EnumStruct>
struct LibraryT { /* Library stuff */ };
// User Defined Enum and Associated Template (which gets specialized later)
namespace MyEnum {
enum Enum {
Value1 /*, ... */
};
};
template <MyEnum::Enum>
struct MyEnumTemplate {};
template <>
struct MyEnumTemplate<MyEnum::Value1> { /* specialized code here */ }; …Run Code Online (Sandbox Code Playgroud) 我想设计一个类来创建内部类型,这些类型是作为模板参数传递的类型的变体.类似下面的非功能性示例:
template <typename T>
class BaseClass
{
public:
typedef T InternalType;
std::vector<InternalType> storage;
};
template <typename Base>
class Injector
{
public:
typedef std::pair<typename Base::InternalType, typename Base::InternalType> RefinedType;
Base<RefinedType> refinedStorage;
};
typedef Injector<BaseClass<int> > InjectedInt; // Should store vector<pair<int, int> >
Run Code Online (Sandbox Code Playgroud)
由于Base是完全指定的类型,Base<RefinedType> refinedStorage;将无法编译.简单地使用模板模板参数将不起作用,因为精炼类型需要基于嵌套模板的参数及其基本类型.
如何基于模板参数的完全指定类型和基本类型实现这种创建类型的模式?
编辑:我希望这是一个任意深度的复合,有多个注入器类型执行级联转换.因此,传递模板模板参数和基本参数变得相当笨拙(特别是在处理复合的基本情况时),理想的解决方案将使用更直接的语法.
我想通过使用模板别名和模板特化的组合来确定模板参数的基础模板.下面的代码在gcc 4.8,6.2.1上编译得很好,但在clang 3.5,3.8上却没有.
#include <iostream>
template <typename T> struct First {};
template <typename T> struct Second {};
template <template <typename> class F, typename T> struct Foo {};
template <typename T> struct Foo<First, T>
{
void f() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template <typename T> struct Foo<Second, T>
{
void f() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template <typename F, typename T> struct Resolution {};
template <typename T> struct Resolution<First<T>, T>
{
template <typename P> using …Run Code Online (Sandbox Code Playgroud) 我想编写一个模板函数,它迭代一个容器std::pair并返回一个模板化的值,两个类型都在该对中.我已经std::map按照以下方式工作:
template <typename T1, typename T2>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const std::map<T1,T2>& zipped)
{
auto unzipped = std::make_pair(std::vector<T1>(), std::vector<T2>());
for (auto& one_two : zipped)
{
unzipped.first.push_back(one_two.first);
unzipped.second.push_back(one_two.second);
}
return unzipped;
}
Run Code Online (Sandbox Code Playgroud)
这很好,但它限制了容器std::map.我想要完成的是让它也适用于类似的东西std::vector<std::pair<T1,T2>>,因为两个容器上的迭代以相同的方式工作.
我试图通过更改模板参数使容器成为模板:
template <typename T1, typename T2, template<typename ... Types> class Container>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const Container<T1,T2>& zipped)
{
//do stuff and return
}
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,如果不使用,则扣除失败std::map因为std::vector仅取决于单一类型.然后我尝试了更多的创意,但编译器只是抱怨更多:
template <typename PairContainerType>
std::pair<std::vector<typename PairContainerType::value_type::first_type>,
std::vector<typename PairContainerType::value_type::second_type>>
unzip(const PairContainerType& zipped)
{
typedef typename PairContainerType::value_type::first_type T1; …Run Code Online (Sandbox Code Playgroud) 我有代码可以在遍历字符串容器时找到并打印出模式的匹配项。打印在模板化的函数foo中执行
编码
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
#include <tuple>
#include <utility>
template<typename Iterator, template<typename> class Container>
void foo(Iterator first, Container<std::pair<Iterator, Iterator>> const &findings)
{
for (auto const &finding : findings)
{
std::cout << "pos = " << std::distance(first, finding.first) << " ";
std::copy(finding.first, finding.second, std::ostream_iterator<char>(std::cout));
std::cout << '\n';
}
}
int main()
{
std::vector<std::string> strs = { "hello, world", "world my world", "world, it is me" };
std::string const pattern = "world";
for …Run Code Online (Sandbox Code Playgroud)