小编W.F*_*.F.的帖子

是否保证模板模板参数调用用户提供的演绎指南

考虑一个例子:

#include <type_traits>
#include <string>

template <template <class> class TT> //#1
struct Foo {
   static void foo() {
      static_assert(std::is_same_v<decltype(TT("abc")), TT<std::string>>);
   }
};

template <class T>
struct Bar {
    Bar(T) {}
};

template <class T>
Bar(T) -> Bar<std::string>; //#2

int main() {
    Foo<Bar>::foo();
}
Run Code Online (Sandbox Code Playgroud)

在推导模板模板参数(#1)的模板参数时,[clang][gcc]似乎都使用用户提供的演绎指南(#2).它是标准兼容功能吗?

c++ templates language-lawyer template-argument-deduction c++17

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

在类的范围内传递指向constexpr函数的指针时,是否滥用推断父模板的参数

我得到的最小例子有点复杂:

struct A { };

template <int>
struct Parent { };

template <int N>
constexpr int operator*(A, Parent<N>*) { return N; }

template <class T>
using ptr = T*;

template <int>
struct Other { };

template <int N>
struct Kid: Parent<N> { 
    static Other<A{} * ptr<Kid>{}> o;
};

int main() {
    Kid<2>{};
}
Run Code Online (Sandbox Code Playgroud)

[GCC]编译代码而没有任何问题,[铛]抱怨匹配Parent针对Kid问题:

prog.cc:7:15: note: candidate template ignored: could not match 'Parent' against 'Kid'
constexpr int operator*(A, Parent<N>*) { return N; } …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer incomplete-type constexpr template-argument-deduction

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

自C++ 17以来可用的构造函数的模板参数推导是否允许显式指定一些类模板参数?

除了对构造函数最明显的模板参数推导使用外,我可以想象一些更复杂的用例,我们只推导出模板类的部分参数,例如:

std::pair<int> p(1, 2); // std::pair<int, int>
Run Code Online (Sandbox Code Playgroud)

虽然这个结构是在函数中推导出模板参数的自然结果,但我找不到这种用法的任何例子.也许是因为具有可变参数模板参数的类的模糊性?

std::tuple<int> t(1, 2, 3); // std::tuple<int, int, int>
Run Code Online (Sandbox Code Playgroud)

然而,这种方式引入语法不会替代太好的"make_*"包装器(参见N3602),其中功能可供我们使用...

c++ templates language-lawyer c++17

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

在派生类中执行成员模板类的部分类内特化是否合法

这是这个问题的延续.如果成员类部分特化是这样的,我特别感兴趣:

struct FooParent {
    template <class>
    struct Bar{ };
};

struct Foo: FooParent {
    template <class T>
    struct Bar<T*> {};
};
Run Code Online (Sandbox Code Playgroud)

我知道这可以在命名空间范围内完成:

template <class T>
struct Foo::Bar<T*>{ };
Run Code Online (Sandbox Code Playgroud)

但我也特别感兴趣的是派生类级别的类内部分特化.

clang和gcc在遇到前者时都会抱怨:

clang声明有明确的模板专业化,显然不会发生:

错误:类范围中'Bar'的显式特化

gcc在这里稍微冗长一点,并说成员模板的特化必须在命名空间范围内执行,这显然不是非派生类的情况.

错误:'template struct FooParent :: Bar'的特化必须出现在命名空间范围内

gcc是否在他的错误消息中?

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

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

如果类型来自std,是否可以创建一个特征来回答?

在使用ADL解决这个问题后,如果传递的类型来自我们的命名空间,则可以创建一个特征来回答:

#include <utility>

namespace helper
{
  template <typename T, typename = void>
  struct is_member_of_sample : std::false_type
  {
  };

  template <typename T>
  struct is_member_of_sample<
      T,
      decltype(adl_is_member_of_sample(std::declval<T>()))> : std::true_type
  {
  };
}

namespace sample
{
  template <typename T>
  auto adl_is_member_of_sample(T && ) -> void;
}

// -- Test it

namespace sample
{
  struct X;
}

struct Y;

static_assert(helper::is_member_of_sample<sample::X>::value, "");
static_assert(not helper::is_member_of_sample<Y>::value, "");

int main(){}
Run Code Online (Sandbox Code Playgroud)

由于显而易见的原因,这不能应用于std命名空间 - 根本没有办法将adl_is_member_of_sample等效命令注入std命名空间而不将自己暴露给未定义的行为.

是否有一些解决方法可以创建特征?

c++ templates type-traits argument-dependent-lookup c++11

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

为什么在gcc中允许带有std :: string的模板化constexpr?

为什么允许在gcc中编译模板版本?它是编译器错误还是与模板一起使用时实际上有效?有人可以向我解释一下吗?

它不能在godbolt.org上使用的clang或其他编译器上编译.

编译错误由constexpr中使用的字符串和字符串流生成.

#include <iostream>
#include <string>
#include <sstream>

template<typename T>
constexpr std::string func1(T a, T b) //Compiles and runs
{
  std::stringstream ss;
  ss << a << b << a+b;
  return ss.str();
}

constexpr std::string func2(int a, int b) //Compile error
{
  std::stringstream ss;
  ss << a << b << a+b;
  return ss.str();
}

int main()
{
  int a = 5;
  int b = 7;
  std::cout << func1(a,b) << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ gcc constexpr c++14

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

尝试访问类的私有成员以防止超载是不正确的?

在尝试创建特征以检查类字段是否公开可用时,我创建了一个代码:

#include <type_traits>
#include <utility>

template <class T, class = void>
struct does_not_have_foo: std::true_type {};

template <class T>
struct does_not_have_foo<T, decltype(std::declval<T>().foo, void())>: std::false_type {};

class Foo {
    int foo;
};

int main() {
    static_assert(does_not_have_foo<Foo>::value);
}
Run Code Online (Sandbox Code Playgroud)

但它似乎未能在[gcc]中编译([clang]似乎在这里更宽松)并出现错误:

prog.cc:8:56: error: 'int Foo::foo' is private within this context
Run Code Online (Sandbox Code Playgroud)

我为我的一些旧代码挖出了类似的东西,归结为以下内容:

template <class T>
auto does_not_have_foo(T t) -> decltype(t.foo, std::false_type()) {
    return {};
}

std::true_type does_not_have_foo(...) { return {}; }

class Foo {
    int foo;
};

int main() {
    static_assert(decltype(does_not_have_foo(Foo{}))::value);
} …
Run Code Online (Sandbox Code Playgroud)

c++ private-members sfinae type-traits language-lawyer

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

为什么在其他函数中声明的函数不参与参数依赖查找?

考虑一个简单的例子:

template <class T>
struct tag { };

int main() {
    auto foo = [](auto x) -> decltype(bar(x)) { return {}; };
    tag<int> bar(tag<int>);
    bar(tag<int>{}); // <- compiles OK
    foo(tag<int>{}); // 'bar' was not declared in this scope ?!
}

tag<int> bar(tag<int>) { return {}; }
Run Code Online (Sandbox Code Playgroud)

[GCC][铛]拒绝编译代码.这段代码在某种程度上是不正确的吗?

c++ templates language-lawyer argument-dependent-lookup c++14

7
推荐指数
2
解决办法
328
查看次数

两个指针的区别是合法的c ++ 17常量表达式吗?

根据cppreference部分核心常量表达式指出19)两个指针之间的减法运算符不是合法的常量表达式,直到c ++ 14.我可以假设以下代码是合法的c ++ 17代码或者这种解释是滥用吗?

int X, Y;

template <long long V>
struct S { };

int main() {
    S<&X - &Y> s;
    (void)s;
}
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer constant-expression c++17

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

是否可以在constexpr上下文中使用指针导致未指定(未定义!)的行为?

根据cppreference(强调我的):

核心常量表达式是任何子表达式中没有以下任何一个的表达式
(...)

  1. 一种表达式,其评估会导致任何形式的核心语言未定义行为(包括有符号整数溢出,除零,数组边界外的指针运算等).是否未指定检测到标准库未定义行为.

另一方面,指针上有几个表达式,结果不是未定义但未指定(参见[expr.rel]/3),例如:

struct A {
    int v;
};

struct B {
    int v;
};

struct C: A, B {} c;

int main() {
    constexpr bool result = &c.A::v < &c.B::v;
    (void)result;
}
Run Code Online (Sandbox Code Playgroud)

代码编译没有gcc的问题,但没有在clang中编写,其中说明无疑是真的:

不同基类的子对象地址的比较尚未明确

但是(根据我的理解),根据cppreference它不应该阻止编译器编译代码.

哪个编译器就在这里 - gcc还是clang?我是否过度解释了cppreference?

c++ language-lawyer unspecified-behavior constexpr c++11

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