在模板 class 中使用 std::conditional 的问题
Issue with using std::conditional in a template class
我正在尝试使用非类型模板参数定义模板 class。然后我使用 std::conditional
从这个模板参数中确定这个 class 的成员类型。我 运行 遇到了一些编译时错误。
下面是MWE。在此 MWE 中,我试图根据条件为真,使模板 class、Mesh
的成员 FiniteElementList
成为 std::vector
或 std::list
(结构化)或假(非结构化)分别。 class、Mesh
包含一些暂时声明的成员函数和友元函数,可能会在稍后阶段定义。
MWE
// c++ standard library headers
#include <list> // std::list
#include <type_traits> // std::conditional
#include <vector> // std::vector
// (un)structured flag
enum class StructuredUnstructured { kStructured = true, kUnstructured = false };
// (un)structured mesh
template <StructuredUnstructured is_structured>
class Mesh {
using Element = double;
using FiniteElementList =
typename std::conditional<is_structured ==
StructuredUnstructured::kStructured,
std::vector<Element>, std::list<Element>>::type;
public:
// constructors
Mesh() = default;
Mesh(const Mesh& m) = default; // copy constructor
Mesh(Mesh&& m) noexcept = default; // move constructor
// assignment operators
Mesh& operator=(const Mesh& m) = default; // copy assignment
Mesh& operator=(Mesh&& m) noexcept = default; // move assignment
~Mesh() = default;
void Indexing() {}
void Properties() {}
friend Mesh ReadMesh() {}
friend void WriteMesh() {}
friend void WriteMeshVTK() {}
private:
FiniteElementList finite_elements_{};
};
int main() {
Mesh<StructuredUnstructured::kUnstructured> unstructured;
Mesh<StructuredUnstructured::kStructured> structured;
}
编译:
我正在尝试使用 clang 编译器进行编译,如下所示
c++ -O3 -Wall -Wextra -Wpedantic -std=c++17 mesh_structure.cpp -o mesh_structure
而我运行进入如下错误
mesh_structure.cpp:34:15: error: functions that differ only in their return type cannot be overloaded
friend Mesh ReadMesh() {}
~~~~ ^
mesh_structure.cpp:46:45: note: in instantiation of template class 'Mesh<StructuredUnstructured::kStructured>' requested here
Mesh<StructuredUnstructured::kStructured> structured;
^
mesh_structure.cpp:34:15: note: previous declaration is here
friend Mesh ReadMesh() {}
~~~~ ^
mesh_structure.cpp:36:15: error: redefinition of 'WriteMesh'
friend void WriteMesh() {}
^
mesh_structure.cpp:36:15: note: previous definition is here
mesh_structure.cpp:38:15: error: redefinition of 'WriteMeshVTK'
friend void WriteMeshVTK() {}
^
mesh_structure.cpp:38:15: note: previous definition is here
3 errors generated.
很奇怪,如果我从 main()
函数中删除第二行 Mesh<StructuredUnstructured::kStructured> structured;
,代码会编译。我不太明白这里出了什么问题。任何帮助将不胜感激。
谢谢。
问题不在于 std::conditional
。让我们首先看一个具有相同问题的更简单的案例:
template <bool>
struct foo {
friend void bar () {};
};
int main()
{
foo<true> x;
foo<false> y;
}
bar
定义了两次,因此出现错误:
<source>: In instantiation of 'struct foo<false>':
<source>:9:16: required from here
<source>:3:17: error: redefinition of 'void bar()'
3 | friend void bar () {};
| ^~~
<source>:3:17: note: 'void bar()' previously declared here
要定义一次,将定义移出模板定义:
template <bool>
struct foo {
friend void bar ();
};
void bar() {}
int main()
{
foo<true> x;
foo<false> y;
}
接下来,另一个问题是您试图声明一个 Mesh<kStructured> ReadMesh()
和一个 Mesh<kUnstructured> ReadMesh()
(在模板定义中,名称 Mesh
指的是 Mesh<is_structured>
,除了一些特殊情况)。
除非您将 ReadMesh
设为函数模板,否则这是行不通的。您不能仅基于 return 值进行重载。一旦 ReadMesh
是一个模板,你就只能像这样匹配匹配的特化:
template <bool> struct foo;
template <bool x> foo<x> bar() {}
template <bool x>
struct foo {
friend foo bar<x> ();
};
int main()
{
foo<true> x;
foo<false> y;
}
我正在尝试使用非类型模板参数定义模板 class。然后我使用 std::conditional
从这个模板参数中确定这个 class 的成员类型。我 运行 遇到了一些编译时错误。
下面是MWE。在此 MWE 中,我试图根据条件为真,使模板 class、Mesh
的成员 FiniteElementList
成为 std::vector
或 std::list
(结构化)或假(非结构化)分别。 class、Mesh
包含一些暂时声明的成员函数和友元函数,可能会在稍后阶段定义。
MWE
// c++ standard library headers
#include <list> // std::list
#include <type_traits> // std::conditional
#include <vector> // std::vector
// (un)structured flag
enum class StructuredUnstructured { kStructured = true, kUnstructured = false };
// (un)structured mesh
template <StructuredUnstructured is_structured>
class Mesh {
using Element = double;
using FiniteElementList =
typename std::conditional<is_structured ==
StructuredUnstructured::kStructured,
std::vector<Element>, std::list<Element>>::type;
public:
// constructors
Mesh() = default;
Mesh(const Mesh& m) = default; // copy constructor
Mesh(Mesh&& m) noexcept = default; // move constructor
// assignment operators
Mesh& operator=(const Mesh& m) = default; // copy assignment
Mesh& operator=(Mesh&& m) noexcept = default; // move assignment
~Mesh() = default;
void Indexing() {}
void Properties() {}
friend Mesh ReadMesh() {}
friend void WriteMesh() {}
friend void WriteMeshVTK() {}
private:
FiniteElementList finite_elements_{};
};
int main() {
Mesh<StructuredUnstructured::kUnstructured> unstructured;
Mesh<StructuredUnstructured::kStructured> structured;
}
编译:
我正在尝试使用 clang 编译器进行编译,如下所示
c++ -O3 -Wall -Wextra -Wpedantic -std=c++17 mesh_structure.cpp -o mesh_structure
而我运行进入如下错误
mesh_structure.cpp:34:15: error: functions that differ only in their return type cannot be overloaded
friend Mesh ReadMesh() {}
~~~~ ^
mesh_structure.cpp:46:45: note: in instantiation of template class 'Mesh<StructuredUnstructured::kStructured>' requested here
Mesh<StructuredUnstructured::kStructured> structured;
^
mesh_structure.cpp:34:15: note: previous declaration is here
friend Mesh ReadMesh() {}
~~~~ ^
mesh_structure.cpp:36:15: error: redefinition of 'WriteMesh'
friend void WriteMesh() {}
^
mesh_structure.cpp:36:15: note: previous definition is here
mesh_structure.cpp:38:15: error: redefinition of 'WriteMeshVTK'
friend void WriteMeshVTK() {}
^
mesh_structure.cpp:38:15: note: previous definition is here
3 errors generated.
很奇怪,如果我从 main()
函数中删除第二行 Mesh<StructuredUnstructured::kStructured> structured;
,代码会编译。我不太明白这里出了什么问题。任何帮助将不胜感激。
谢谢。
问题不在于 std::conditional
。让我们首先看一个具有相同问题的更简单的案例:
template <bool>
struct foo {
friend void bar () {};
};
int main()
{
foo<true> x;
foo<false> y;
}
bar
定义了两次,因此出现错误:
<source>: In instantiation of 'struct foo<false>':
<source>:9:16: required from here
<source>:3:17: error: redefinition of 'void bar()'
3 | friend void bar () {};
| ^~~
<source>:3:17: note: 'void bar()' previously declared here
要定义一次,将定义移出模板定义:
template <bool>
struct foo {
friend void bar ();
};
void bar() {}
int main()
{
foo<true> x;
foo<false> y;
}
接下来,另一个问题是您试图声明一个 Mesh<kStructured> ReadMesh()
和一个 Mesh<kUnstructured> ReadMesh()
(在模板定义中,名称 Mesh
指的是 Mesh<is_structured>
,除了一些特殊情况)。
除非您将 ReadMesh
设为函数模板,否则这是行不通的。您不能仅基于 return 值进行重载。一旦 ReadMesh
是一个模板,你就只能像这样匹配匹配的特化:
template <bool> struct foo;
template <bool x> foo<x> bar() {}
template <bool x>
struct foo {
friend foo bar<x> ();
};
int main()
{
foo<true> x;
foo<false> y;
}