如何使用默认参数转发声明全局或命名空间中的模板函数?

How to forward declare a template function in global or namespace with default argument?

template<typename T> void foo (T t, int i = 0); // declaration

int main () { foo(1, 0); } // error!! 

template<typename T> void foo (T t, int i = 0) {} // definition

以上是针对较大问题的最小可重现示例,其中涉及许多头文件。尝试使用默认参数转发声明会导致以下编译:

error: redeclaration of ‘template void foo(T, int)’ may not have default arguments [-fpermissive]

如何解决这个问题?

默认参数,如int i = 0,被视为定义。因此重复它是 ODR-violation.

不知道具体原因,除了标准明确这样说

Each of the following is termed a definable item:
[...]
(1.6) a default argument for a parameter (for a function in a given > scope)
[...] No translation unit shall contain more than one definition of any definable item.

http://eel.is/c++draft/basic.def.odr

解决方案是让默认参数只出现一次,可能在声明中出现(而不是在定义中重复出现)。