Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板结构标记部分专业化,带有enable_if或类似内容_C++_Templates_C++14 - Fatal编程技术网

C++ 模板结构标记部分专业化,带有enable_if或类似内容

C++ 模板结构标记部分专业化,带有enable_if或类似内容,c++,templates,c++14,C++,Templates,C++14,我正在寻找一种使用std::enable_if或类似的方法来扩展一个已经存在的定制点,它将像下面的a专业化一样工作(只是一个虚拟示例): //外部库中的自定义点结构 模板 结构A { T型; }; //--------------------------------------------- #包括 模板 概念bool Floating=std::is_Floating_point::value; //支持enable_if风格,无需更改外部库 模板 结构A { typedef std::向量类

我正在寻找一种使用std::enable_if或类似的方法来扩展一个已经存在的定制点,它将像下面的
a
专业化一样工作(只是一个虚拟示例):

//外部库中的自定义点结构
模板
结构A
{
T型;
};
//---------------------------------------------
#包括
模板
概念bool Floating=std::is_Floating_point::value;
//支持enable_if风格,无需更改外部库
模板
结构A
{
typedef std::向量类型;
};
int main()
{
静态断言(std::is_same::value,“”);
静态断言(std::is_same::value,“”);
返回0;
}
问题是我有以下限制:

  • 无法修改结构A以接受两个模板参数
    template
    ,因为此结构是在外部库中定义的
  • 不能使用概念精简版(因为有些人认为有必要将其标准化推迟到未来几年…)
  • 不要用
    A
    之类的东西把所有呼叫站点上的代码弄乱,因为那样会很难看而且容易出错(宏使用也是如此)
  • 不想编写外部代码生成器

我怀疑这是可能的,但我记得过去有人说不需要概念lite,因为它们或多或少可以通过元编程来模拟,所以我希望有人能证明我错了。

为了确保我正确理解这个问题,你是否在寻找与你发布的代码等效的东西,但是只使用C++14(没有概念)

我认为您提到的第一个限制(“不能修改结构A以接受两个模板参数”)是最大的问题。我不知道有什么方法可以在不使用概念的情况下,一次专门化一个现有的单参数模板来处理整个类型的“类”(例如浮点类型)

所以我认为对你的问题的严格回答是,“不,这是不可能的。”

如果您可以修改A的第一个声明,那么它会容易得多。就我个人而言,我觉得有时候以“我不能修改这个外部库”开头的问题的最佳答案是,“去看看如何修改它,然后再回来问你的问题。”

我在下面提供了一个替代解决方案的想法,但您的问题中缺少太多信息,无法说明它是否适合您。

我假设这个外部库拉入您提供的某个头,以便查看您的专门化,并且无论何时更改该头,您都将重新编译该库。(如果不是这样,请编辑您的问题以更好地解释情况。)

在你想把你的专业化放在同一个头中,你可以考虑使用一些老学校的预处理器技巧来解决问题。这很难看,你必须小心你的

#include
语句的顺序,但它可能会帮你完成工作:

// customisation point structure in external lib
template<typename T>
struct A
{
    typedef T type;
};

//---------------------------------------------
#include <vector>

template<typename T, bool is_float>
struct Av2impl
{
    typedef T type;
};

template<typename T>
struct Av2impl<T, true>
{
    typedef std::vector<T> type;
};

template<typename T>
struct Av2
{
    typedef typename Av2impl<T, std::is_floating_point<T>::value>::type type;
};

// force all code after this point to use Av2 instead of A
#define A Av2

int main()
{
    static_assert(std::is_same<A<int>::type, int>::value, "");
    static_assert(std::is_same<A<float>::type, std::vector<float>>::value, "");

    return 0;
}
//外部库中的自定义点结构
模板
结构A
{
T型;
};
//---------------------------------------------
#包括
模板
结构Av2impl
{
T型;
};
模板
结构Av2impl
{
typedef std::向量类型;
};
模板
结构Av2
{
typedef typename Av2impl::type type;
};
//强制在此点之后的所有代码使用Av2而不是
#定义一个Av2
int main()
{
静态断言(std::is_same::value,“”);
静态断言(std::is_same::value,“”);
返回0;
}

概念不是c++14。您可能想重新标记您的问题。在添加
#include
后,我使用“g++-std=c++2a-fconcepts”为您编译。问题是什么?我知道你不想更改所有的呼叫站点,但是你可以做一些类似于
使用X=std::conditional\u t,A,B>
,然后使用
X
而不是
A
(其中
B
是“专门化”)。从技术上讲,这非常接近规范化,根本不容易出错。”我不想用“你使用
a
,或者它确实是一个定制点,所以你使用
external_library::f(yourType{})之类的东西把所有调用站点上的代码搞得一团糟
这需要
A
@YSC和aschepler阅读问题-我知道概念是针对C++20的-我需要一些适用于C++14的东西可能外部库有一些使用
typename A::type的模板代码-因此,您可能需要在外部库的头中实施黑客攻击,但不允许它定义冲突的类模板。如果库不只是标题,希望它的非模板、显式实例化或显式专门化的定义都不会在其损坏的名称中包含
a
的专门化。@John Lindgren我知道如何侵入性地修改
templateA{…}
因此,问题是如何不这样做,而仍然获得没有概念的非侵入式概念风格。您的解决方案的问题正如aschepler所指出的,黑客必须进入外部库,因此在这种情况下,我只需更改其中的基本模板并重新编译它。@DomenVrankar我根据您的问题对您的情况做了一些假设,这些假设听起来似乎不正确。我编辑了我的问题以澄清这些假设。下一次,我一定会在尝试帮助之前要求澄清。@johnlingren你已经展示了一个有趣的解决方案,别误会我。只是我一直在寻找一个干净的解决方案,它不会让我们的代码更难维护,也不会让外部代码成为我们维护负担的一部分。我试图把这个问题简化为最基本的问题,但这样做的时候,我甚至没有注意到我没有提供足够的信息。因为没有其他解决办法
// customisation point structure in external lib
template<typename T>
struct A
{
    typedef T type;
};

//---------------------------------------------
#include <vector>

template<typename T, bool is_float>
struct Av2impl
{
    typedef T type;
};

template<typename T>
struct Av2impl<T, true>
{
    typedef std::vector<T> type;
};

template<typename T>
struct Av2
{
    typedef typename Av2impl<T, std::is_floating_point<T>::value>::type type;
};

// force all code after this point to use Av2 instead of A
#define A Av2

int main()
{
    static_assert(std::is_same<A<int>::type, int>::value, "");
    static_assert(std::is_same<A<float>::type, std::vector<float>>::value, "");

    return 0;
}