标签: variable-templates

我可以使用变量模板来声明另一个变量模板吗?

随着C++ 14中的变量模板(以及Clang已经支持它们)和标准is_same_v类型特征的提议,我认为能够制作新的类型特征如下:

template<typename T>
constexpr bool is_const_and_volatile{std::is_const_v<T> && std::is_volatile_v<T>};
Run Code Online (Sandbox Code Playgroud)

唉,这会导致错误等同于以下SSCCE(这个包含下面提到的所有内容):

#include <type_traits>

template<typename T>
constexpr bool is_pointer{std::is_pointer<T>::value};

template<typename T>
constexpr bool foo{is_pointer<T>};

int main() {
    //foo<int *>;
}
Run Code Online (Sandbox Code Playgroud)

main评论中,Clang吐出以下内容:

警告:变量is_pointer<type-parameter-0-0>具有内部链接但未定义

它看起来定义为我的(注意,更改Tint *foo正常工作).在取消注释行main实例foo给出了这样的(再次,Tint *优良工程):

错误:constexpr变量foo<int *>必须由常量表达式初始化

但是,foo使用以下旧语法替换会导致两个实例都正常工作:

constexpr bool foo{std::is_pointer<T>::value};
Run Code Online (Sandbox Code Playgroud)

关于变量模板有什么我想念的吗?有没有办法它们构建新的变量模板,或者我是否被迫使用旧的语法来构建新的模板,并且在将它们用于其他代码时只享受语法糖?

c++ variable-templates c++14

8
推荐指数
1
解决办法
398
查看次数

实例化变量模板时要考虑代码的哪一部分?

在以下程序中,全局变量isCompleteType<Apple>由 clang 和 gcc 以不同的方式初始化(​​位于Godbolt.org 上):

template <class T>
constexpr bool IsCompleteTypeHelper (decltype (sizeof (T))) { return true; }

template <class T>
constexpr bool IsCompleteTypeHelper (...)                   { return false; }

template <class T>
bool isCompleteType = IsCompleteTypeHelper<T> (0);


class Apple;


int main ()
{
    return isCompleteType<Apple>;
}


class Apple {};
Run Code Online (Sandbox Code Playgroud)
  • Clang 10.0.0 初始化isCompleteType<Apple>true.
  • Gcc 9.3 初始化isCompleteType<Apple>false.

由于Apple可以生成变量的定义true的实例化之后isCompleteType,因此我得出结论,编译器在初始化变量时会执行以下操作。

  • Clang 考虑整个翻译单元。
  • Gcc …

c++ language-lawyer incomplete-type variable-templates c++14

7
推荐指数
0
解决办法
78
查看次数

内联声明变量模板的目的是什么?

C++14 添加了变量模板,它定义了相关变量组。在标准库中,变量模板用于访问每个类型特征的值成员:

template<class T>
inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
Run Code Online (Sandbox Code Playgroud)

C++17 添加了内联变量以更好地支持仅头文件库,这些库可以包含在同一应用程序内的多个源文件中(不同的翻译单元中允许相同的内联变量定义)。但就变量模板而言,无论如何它们都可以在程序中具有多个定义。那么,如果变量模板已经免于 ODR,还有什么理由将它们声明为内联呢?


只要很多人都关注constexpr差异inline constexpr,这是另一个有趣的问题,我就想忽略constexpr这次讨论的目的。

template <typename T>
bool myVar = sizeof(T) > 1;
Run Code Online (Sandbox Code Playgroud)

它与以下内容有何不同:

template <typename T>
inline bool myVar = sizeof(T) > 1;
Run Code Online (Sandbox Code Playgroud)

c++ templates variable-templates c++17 inline-variable

7
推荐指数
1
解决办法
568
查看次数

转发非类型参数会导致变量模板上出现不同的行为

这似乎是另一个"谁做得好"?问题,因为gcc 6.0.0和clang 3.7.0表现不同.

假设我们有一个变量模板,它采用const char *非模板参数,并且专用于给定的指针:

constexpr char INSTANCE_NAME[]{"FOO"};

struct Struct{ void function() const { std::cout << __PRETTY_FUNCTION__; } };
std::ostream &operator <<(std::ostream &o, const Struct &) { return o << INSTANCE_NAME; }

template <const char *> char   Value[]{"UNKNOWN"};
// spezialization when the pointer is INSTANCE_NAME
template <            > Struct Value<INSTANCE_NAME>{};
Run Code Online (Sandbox Code Playgroud)

请注意,模板变量具有不同的类型,具体取决于特化.十,我们有两个模板函数,每个函数都有一个const char *非模板参数,并将转发给变量模板:

template <const char *NAME> void print()
{
    std::cout << Value<NAME> << '\n';
}

template <const char *NAME> void …
Run Code Online (Sandbox Code Playgroud)

c++ template-specialization variable-templates c++14

6
推荐指数
2
解决办法
232
查看次数

变量模板的部分专业化

我知道我可以部分专门化类模板,我知道我不能部分指定函数模板.

变量模板怎么样?我找不到关于它们是否可以部分专业化的文档.

c++ templates partial-specialization language-lawyer variable-templates

6
推荐指数
1
解决办法
416
查看次数

可以在C++ 14中使用类型值元函数作为变量别名吗?

在查看C++ 14的元函数别名提议(TransformationTraits Redux,v2,N3655)时,我注意到,不仅类型转换类型(例如add_const),类型到值元函数(例如is_void)也是类型别名.(N3797中没有).

混淆类型对元函数的值是否有任何优势?我认为,可以在没有这些别名的情况下使用它们,例如enable_if_t<is_void<T>::value,T>enable_if_t<is_void<T>{}(),T>存在转换操作时.(我猜is_void<T>::type::value是一样的is_void<T>::value)

如果类型值元函数需要是别名,不要将它们作为变量模板别名(我没有C++ 14编译器,也从不使用变量模板.所以语法可能是错误的)?例如别名is_void

template <class T>
constexpr bool is_void_t = is_void<T>::value;
Run Code Online (Sandbox Code Playgroud)

代替

template <class T>
using is_void_t = typename is_void<T>::type;
Run Code Online (Sandbox Code Playgroud)

然后一个人可以在enable_if_t<is_void_t<T>,T>没有助推风格的情况下写作enable_if,并且构图表达将更容易(例如enable_if_t<(is_void_t<T> || is_integral_t<T>),T>

c++ type-traits template-aliases variable-templates c++14

5
推荐指数
1
解决办法
526
查看次数

无法在不定义模板变量的情况下声明模板变量

我想在头文件中转发声明变量模板,然后在单独的编译单元中进行实际实例化.

我被引导相信C++ 14变量模板的运行方式与静态类变量非常相似.不幸的是,这似乎并非如此,它阻止我向前声明我的变量模板.

template <typename T> struct Variable {
    static int variable;
};

template <typename T> 
extern int variable;

int main() {
    (void) Variable<char>::variable;
    // (void) variable<char>;                   // <-- line 10
}

template <> int Variable<char>::variable = 42;
template <> int variable<char> = 23;
Run Code Online (Sandbox Code Playgroud)

上面的代码示例在GCC下编译并按原样运行.但是,取消注释第10行会产生编译时错误:

specialization of 'variable<char>' after instantiation
    template <> int variable<char> = 23;
                     ^
Run Code Online (Sandbox Code Playgroud)

c++ templates variable-templates c++14

5
推荐指数
1
解决办法
493
查看次数

模板变量的特化(针对模板模板类)

当我尝试为通用容器(例如std::list<...>,而不是特定容器,例如std::list<double>)专门化模板变量时,我收到链接错误gcc 5.3(但不是clang 3.5

/tmp/ccvxFv3R.s: Assembler messages:
/tmp/ccvxFv3R.s:206: Error: symbol `_ZL9separator' is already defined
Run Code Online (Sandbox Code Playgroud)

http://coliru.stacked-crooked.com/a/38f68c782d385bac

#include<string>
#include<iostream>
#include<list>
#include<forward_list>
#include<vector>

template<typename T> std::string const separator = ", ";
template<typename... Ts> std::string const separator<std::list<Ts...>        > = "<->";
template<typename... Ts> std::string const separator<std::forward_list<Ts...>> = "->";

int main(){

    std::cout << separator<std::vector<double>> << '\n';
    std::cout << separator<std::list<double>> << '\n';
    std::cout << separator<std::forward_list<double>> << '\n';

}
Run Code Online (Sandbox Code Playgroud)

(这可以很好地编译clang 3.5并按预期工作。此外,可变参数模板不是导致问题的原因,我尝试使用非可变参数模板)。

如果这不是 中的错误gcc,您认为有解决方法吗?我尝试使用类专业化,但也不可能:

template<class T>
struct separator{ …
Run Code Online (Sandbox Code Playgroud)

c++ gcc template-specialization variable-templates c++14

5
推荐指数
1
解决办法
836
查看次数

C++ make变量的类型取决于上下文?

我有以下代码:

// Case #1
float f = 1.0f;
float f2 = sqrt(f * pi);

// Case #2
double d = 1.0;
double d2 = sqrt(d * pi);
Run Code Online (Sandbox Code Playgroud)

有什么办法来定义变量pi,以便operator*sqrt将在操作floatS IN案例#1,但在操作double中的情况#2秒?

也许C++ 14变量模板可能有用吗?

c++ variable-templates c++14

5
推荐指数
1
解决办法
247
查看次数

类模板中静态变量模板的部分特化

如果我进行部分专业化,我会从 clang 和 g++ 得到不同的结果。

template < typename T>
class X
{
    public:
        T i;
        X(T _i): i{_i}{}

        operator T(){ return i; }
};  

template < typename T2 >
class Y
{
    public:
        template <typename T>
            static X<T> x_in_y;
};  

template< typename T2> 
template< typename T>
X<T> Y<T2>::x_in_y{200};


template<>
template<>
X<float> Y<int>::x_in_y<float>{100};

template<>
template<>
X<int> Y<int>::x_in_y<int>{101};

template<  >
template< typename T >
X<T> Y<bool>::x_in_y{77};



int main()
{
    std::cout << Y<int>::x_in_y<int> << std::endl;
    std::cout << Y<int>::x_in_y<float> << std::endl;

    std::cout << Y<float>::x_in_y<float> …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization variable-templates c++14

5
推荐指数
0
解决办法
102
查看次数

喷涂结构

我有一堆这样的结构,其中成员数量不断增加,但成员命名却保持一致:

struct one { int a; };
struct two { int a; int b; };
struct three { int a; int b; int c; };
Run Code Online (Sandbox Code Playgroud)

我也有一个模板化函数,我希望接受以下这些结构的成员之一:

template <typename T, typename ... ARGS> // T will be one, two, or three
void func(ARGS... args); // This should take 1, 2, or 3, int arguments respectively
Run Code Online (Sandbox Code Playgroud)

我希望能够这样称呼:

two foo;

func<two>(splatter(foo));
Run Code Online (Sandbox Code Playgroud)

哪里splatter会以某种方式分裂,foo以便解决func<two>(foo.a, foo.b)

显然,我可以只扩展此内联,而无需splatter,但是我调用的代码func本身很容易被模板化。我已经尝试过使用,initializer_list但是我不知道如何仅基于模板类型来构建一个。

不幸的是,我的编译器也不支持constexpr if对splat的调用func或构建initializer_list …

c++ struct initializer-list splat variable-templates

5
推荐指数
1
解决办法
159
查看次数

如何在模板变量定义中引入static_assert

如何引入static_assert模板变量定义?

我的尝试是使用 lambda 函数:

#include <type_traits>
#include <utility>

#include <cstdlib>

namespace
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"

template< typename F >
F f = ([] () { static_assert(std::is_default_constructible< F >{}); }(), F{});

#pragma clang diagnostic pop
}

struct L
{
    L() = default;
    L(L const &) = delete;
    L(L &&) = delete; 
};

int
main()
{
    static_cast< void >(f< L >);
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

但对于不可移动的对象,不可能以这种方式构造值对象。

使用逗号运算符我无法在 form 中执行值初始化F f = ([] () { …

c++ static-assert type-traits variable-templates c++14

2
推荐指数
1
解决办法
700
查看次数

变量模板的开销

C++ 14引入了变量模板(Variable templates).

template<class T>
constexpr T pi = T(3.1415926535897932385);  // variable template

template<class T>
T circular_area(T r) // function template
{
    return pi<T> * r * r; // pi<T> is a variable template instantiation
}
Run Code Online (Sandbox Code Playgroud)

在二进制内存占用和运行速度方面,使用它的开销是多少?

c++ variable-templates c++14

1
推荐指数
1
解决办法
238
查看次数